Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add NEW custom product attribute in WooCommerce programmatically?

I have a pretty big database of products on a webpage. This webpage was written in PHP, and now I need to migrate its database to a Wordpress (WooCommerce) site. I already figured out how to add the products. I made a php file (outside wordpress) with this header, so I can use all of the wordpress functions:

include('../wp/wp-load.php');
require_once('../wp/wp-admin/includes/media.php');
require_once('../wp/wp-admin/includes/file.php');
require_once('../wp/wp-admin/includes/image.php');

First I get all products from the old database to a php array $items, and then loop through this array using a foreach loop. Inside the loop I have this code:

$user_id = get_current_user();
$post_id = wp_insert_post(array(
    'post_author' => $user_id,
    'post_title' => $item['termek'],
    'post_content' => $item['reszletes_leiras'],
    'post_status' => 'publish',
    'post_type' => "product",
));
wp_set_object_terms( $post_id, 'simple', 'product_type' );
update_post_meta( $post_id, '_visibility', 'visible' );
update_post_meta( $post_id, '_stock_status', 'instock');
update_post_meta( $post_id, 'total_sales', '0' );
update_post_meta( $post_id, '_downloadable', 'no' );
update_post_meta( $post_id, '_virtual', 'no' );
update_post_meta( $post_id, '_regular_price', $item['brutto_ar'] );
update_post_meta( $post_id, '_sale_price', $item['brutto_ar'] );
update_post_meta( $post_id, '_purchase_note', '' );
update_post_meta( $post_id, '_featured', 'no' );
update_post_meta( $post_id, '_weight', '' );
update_post_meta( $post_id, '_length', '' );
update_post_meta( $post_id, '_width', '' );
update_post_meta( $post_id, '_height', '' );
update_post_meta( $post_id, '_sku', $item['id'] );
update_post_meta( $post_id, '_product_attributes', array() );
update_post_meta( $post_id, '_sale_price_dates_from', '' );
update_post_meta( $post_id, '_sale_price_dates_to', '' );
update_post_meta( $post_id, '_price', '' );
update_post_meta( $post_id, '_sold_individually', '' );
update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', 'no' );
update_post_meta( $post_id, '_stock', '' );

My problem is that I also have an array in $item['parameterek'], which looks kile this:

["Some custom attribute"] => (string)"Something"
["Another custom attribute"] => (string)"Something else"

Now I need to add these fields to the products as custom attributes. The array key is the name, and the value is... the value, of course. I tried to do it this way, but this code seems to do nothing:

foreach(array_keys($item['parameterek']) as $key) {
    register_attribute($key);
}
wproduct_set_attributes($post_id, $item['parameterek']);

function register_attribute($name){
    $paname = 'pa_' . htmlspecialchars(stripslashes($name));
    $permalinks = get_option('woocommerce_permalinks');
    $taxonomy_data = array(
                        'hierarchical'          => false,
                        'update_count_callback' => '_update_post_term_count',
                        'labels'                => array(
                                'name'              => $name,
                                'singular_name'     => $name,
                                'search_items'      => sprintf( __( 'Search %s', 'woocommerce' ), $label ),
                                'all_items'         => sprintf( __( 'All %s', 'woocommerce' ), $label ),
                                'parent_item'       => sprintf( __( 'Parent %s', 'woocommerce' ), $label ),
                                'parent_item_colon' => sprintf( __( 'Parent %s:', 'woocommerce' ), $label ),
                                'edit_item'         => sprintf( __( 'Edit %s', 'woocommerce' ), $label ),
                                'update_item'       => sprintf( __( 'Update %s', 'woocommerce' ), $label ),
                                'add_new_item'      => sprintf( __( 'Add New %s', 'woocommerce' ), $label ),
                                'new_item_name'     => sprintf( __( 'New %s', 'woocommerce' ), $label )
                            ),
                        'show_ui'           => false,
                        'query_var'         => true,
                        'rewrite'           => array(
                            'slug'         => empty( $permalinks['attribute_base'] ) ? '' : trailingslashit( $permalinks['attribute_base'] ) . sanitize_title( $name ),
                            'with_front'   => false,
                            'hierarchical' => true
                        ),
                        'sort'              => false,
                        'public'            => true,
                        'show_in_nav_menus' => false,
                        'capabilities'      => array(
                            'manage_terms' => 'manage_product_terms',
                            'edit_terms'   => 'edit_product_terms',
                            'delete_terms' => 'delete_product_terms',
                            'assign_terms' => 'assign_product_terms',
                        )
                    );
    register_taxonomy($paname, array('product'), $taxonomy_data);
}

function wcproduct_set_attributes($post_id, $attributes) {
    $i = 0;
    // Loop through the attributes array
    foreach ($attributes as $name => $value) {
        $product_attributes[$i] = array (
            'name' => 'pa_' . htmlspecialchars(stripslashes($name)), // set attribute name
            'value' => $value, // set attribute value
            'position' => 1,
            'is_visible' => 1,
            'is_variation' => 0,
            'is_taxonomy' => 1
        );

        $i++;
    }
    update_post_meta($post_id, '_product_attributes', $product_attributes);
}

So my question is: What is the easiest way to add custom product attributes from an array using PHP?

like image 677
Balázs Varga Avatar asked Oct 23 '25 13:10

Balázs Varga


1 Answers

I recently come with the same issue as you. First you need to think about the options of each attribute.

is_visible will make the attribute visible in the product page if set to 1, and only visible in the edit product page if set to 0.

is_variation is used to create variations of same product for said custom attribute. If set to 1, indicates to Woocommerce that variations exist, so it will look for posts with 'post_type' => "product_variation" that are related to original product post through attribute 'post_parent' set as original product post_id like 'post_parent' => $original_post_id

is_taxonomy is used to categorize the product based in said custom attribute. For example, think in clothes being the products to be sold, you create a custom attribute called gender to categorize the products depending on the gender.

As it seems reading your question, you just need simple custom attributes with string values visible in the product page:

["Some custom attribute"] => (string)"Something"
["Another custom attribute"] => (string)"Something else"

so the way of implementing your loop would be something like this:

[loop]

$user_id = get_current_user();
$post_id = wp_insert_post(array(
    'post_author' => $user_id,
    'post_title' => $item['termek'],
    'post_content' => $item['reszletes_leiras'],
    'post_status' => 'publish',
    'post_type' => "product",
));
wp_set_object_terms( $post_id, 'simple', 'product_type' );
update_post_meta( $post_id, '_visibility', 'visible' );
update_post_meta( $post_id, '_stock_status', 'instock');
update_post_meta( $post_id, 'total_sales', '0' );
update_post_meta( $post_id, '_downloadable', 'no' );
update_post_meta( $post_id, '_virtual', 'no' );
update_post_meta( $post_id, '_regular_price', $item['brutto_ar'] );
update_post_meta( $post_id, '_sale_price', $item['brutto_ar'] );
update_post_meta( $post_id, '_purchase_note', '' );
update_post_meta( $post_id, '_featured', 'no' );
update_post_meta( $post_id, '_weight', '' );
update_post_meta( $post_id, '_length', '' );
update_post_meta( $post_id, '_width', '' );
update_post_meta( $post_id, '_height', '' );
update_post_meta( $post_id, '_sku', $item['id'] );
update_post_meta( $post_id, '_product_attributes', array() );
update_post_meta( $post_id, '_sale_price_dates_from', '' );
update_post_meta( $post_id, '_sale_price_dates_to', '' );
update_post_meta( $post_id, '_price', '' );
update_post_meta( $post_id, '_sold_individually', '' );
update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', 'no' );
update_post_meta( $post_id, '_stock', '' );
$i = 0;
$product_attributes = array();
foreach($item['parameterek'] as $key => $value){
    $product_attributes[sanitize_title($key)] = array (
            'name' => wc_clean($key), // set attribute name
            'value' => $value, // set attribute value
            'position' => $i,
            'is_visible' => 1,
            'is_variation' => 0,
            'is_taxonomy' => 0
        );
     $i++;
}
update_post_meta($post_id, '_product_attributes', $product_attributes);
[/loop]

In case one of your products has variations the way of implementing is, first create the base product as you already do. Then saving said custom attribute as variation.

$attr[sanitize_title($custom_attribute_name)] = array(
     'name'=> wc_clean($custom_attribute_name),
     'value'=> $string_custom_attr_values,
     'position' => $position,
     'is_visible' => 1,
     'is_variation' => 1,
     'is_taxonomy' => 0
 );

Where $string_custom_attr_values is a string of the values of variations separated by | . For example, a custom attribute of sizes for variations then $string_custom_attr_values = 'S|M|L|XL';

And then you will need a new loop inside the one you already have for $items to create the variations of said product, something like this following the previous example of variation of sizes:

$string_custom_attr_values = 'S|M|L|XL';
$arr_custom_attr_values = explode("|", $string_custom_attr_values);
$total_variations = count($arr_custom_attr_values);
$variation_post_id = $post_id;
for($i = 1; $i <= $total_variations; $i++) {
    $variation_post_id += $i;
    $variation_post = array(
        'post_title' => 'Variation #' . $variation_post_id . ' of ' . $item['termek'],
        'post_name'     => 'product-' . $variation_post_id . '-variation',
        'post_status'   => 'publish',
        'post_parent'   => $post_id,
        'post_type'     => 'product_variation',
        'guid'          =>  home_url() . '/product_variation/product-' . $variation_post_id . '-variation',
        'menu_order'    =>  $i
 );

    // Insert the variation post into the database
    $variation_post_id = wp_insert_post( $variation_post );
    update_post_meta( $variation_post_id, 'attribute_'.$custom_attribute_name, $arr_custom_attr_values[$i-1]);

    /*Rest of the post_meta like in the base product*/

}//end for

Hope I have been clear enough.

like image 92
Dez Avatar answered Oct 26 '25 03:10

Dez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!