12

How can I create attributes for WooCommerce from a plugin? I find only :

wp_set_object_terms( $object_id, $terms, $taxonomy, $append);

From this stack-question

But this approach required id of some product. I need to generate some attributes not attached to any products.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
WebArtisan
  • 3,996
  • 10
  • 42
  • 62
  • But a default attribute *is* product-specific, so I am not sure what you are asking. – helgatheviking Apr 09 '15 at 23:34
  • I need generate some default attributes here http://joxi.ru/gmvegqWt185Vra when my plugin activated. And I can do it manually, but I want - automatically – WebArtisan Apr 09 '15 at 23:40
  • But what do you mean by default attribute? Since as I mentioned, a term can only be the default for a specific product. – helgatheviking Apr 09 '15 at 23:45
  • When i create attribute like category, i not attached him to any of products right? So i need GENERATE few attributes without binding to product. – WebArtisan Apr 09 '15 at 23:51
  • Ah ok.... so I think you want to create a term. In which case you will need [`wp_insert_term()`](http://codex.wordpress.org/Function_Reference/wp_insert_term) – helgatheviking Apr 09 '15 at 23:55
  • second param this func is taxonomy, what taxonomy is attributes? regular taxonomy for categoies taxonomy=category Product category is taxonomy=product_cat. i can't find what taxonomy is attributes ? Look - i`ts a page or i'm wrong? http://joxi.ru/xAee01MtX7WYAy – WebArtisan Apr 10 '15 at 00:07
  • See my answer below. Attributes isn't a taxonomy in its own right. Each attribute (ex: color, size, font) is its own taxonomy. – helgatheviking Apr 10 '15 at 00:40

2 Answers2

25

To create a term you can use wp_insert_term()

like so:

wp_insert_term( 'red', 'pa_colors' );

where colors is the name of your attribute. The taxonomy name of an attribute is always prepended by pa_.

Edit Attributes are merely custom taxonomies. Or you could say they are dynamic taxonomies that are manually created by the user in the back-end. Still, all the same, custom taxonomy rules apply.

You can see the source code here which loops through the attributes and runs register_taxonomy() on each. So to create a new attribute (remember it is just a taxonomy) then you need to run register_taxonomy() and simple prepend pa_ to the start of the taxonomy name.

Mimicking some of the values of the taxonomy args from core would get you something like this for a 'Colors' attribute.

/**
 * Register a taxonomy.
 */
function so_29549525_register_attribute() {

    $permalinks = get_option( 'woocommerce_permalinks' );

    $taxonomy_data = array(
                        'hierarchical'          => true,
                        'update_count_callback' => '_update_post_term_count',
                        'labels'                => array(
                                'name'              => __( 'My Colors', 'your-textdomain' ),
                                'singular_name'     => __( 'Color', 'your-textdomain' ),
                                'search_items'      => __( 'Search colors', 'your-textdomain' ),
                                'all_items'         => __( 'All colors', 'your-textdomain' ),
                                'parent_item'       => __( 'Parent color', 'your-textdomain' ),
                                'parent_item_colon' => __( 'Parent color:', 'your-textdomain' ),
                                'edit_item'         => __( 'Edit color', 'your-textdomain' ),
                                'update_item'       => __( 'Update color', 'your-textdomain' ),
                                'add_new_item'      => __( 'Add new color', 'your-textdomain' ),
                                'new_item_name'     => __( 'New color', 'your-textdomain' )
                            ),
                        'show_ui'           => false,
                        'query_var'         => true,
                        'rewrite'           => array(
                            'slug'         => empty( $permalinks['attribute_base'] ) ? '' : trailingslashit( $permalinks['attribute_base'] ) . sanitize_title( 'colors' ),
                            '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( 'pa_my_color', array('product'), $taxonomy_data );

}
add_action( 'woocommerce_after_register_taxonomy', 'so_29549525_register_attribute' );

Update 2020-11-18

Attribute taxonomies are stored in the {$wpdb->prefix}woocommerce_attribute_taxonomies database table. And from there WooCommerce runs register_taxonomy() on each one that's found in the table. So in order to create an attribute taxonomy, a row should be added to this table. WooCommerce has a function wc_create_attribute() that will handle this for us. (Since 3.2+).

My conditional logic to test if the attribute exists is not the greatest and I would advise using some kind of version option in your plugin's update routine. But as an example of using wc_create_taxonomy() this should insert an attribute called "My Color".

/**
 * Register an attribute taxonomy.
 */
function so_29549525_create_attribute_taxonomies() {

    $attributes = wc_get_attribute_taxonomies();

    $slugs = wp_list_pluck( $attributes, 'attribute_name' );

    if ( ! in_array( 'my_color', $slugs ) ) {

        $args = array(
            'slug'    => 'my_color',
            'name'   => __( 'My Color', 'your-textdomain' ),
            'type'    => 'select',
            'orderby' => 'menu_order',
            'has_archives'  => false,
        );

        $result = wc_create_attribute( $args );

    }
}
add_action( 'admin_init', 'so_29549525_create_attribute_taxonomies' );
helgatheviking
  • 25,596
  • 11
  • 95
  • 152
  • 1
    no, it will creates value for EXISTING attribute. I need create my own pa_**** elements – WebArtisan Apr 10 '15 at 08:20
  • 1
    Then you need to `register_taxonomy()`. See the edit. – helgatheviking Apr 10 '15 at 10:17
  • @helgatheviking is there other way to create woocommerce attribute other than using register_taxonomy? register_taxonomy uses too much resource and i can't use it because im create products and attributes programmatically. – jameshwart lopez Jun 02 '16 at 11:33
  • @jameshwartlopez WooCommerce attributes *are* WordPress taxonomies, so you need `register_taxonomy()`. As a possible alternative you *might* be able to use the API? But I'm not sure. – helgatheviking Jun 02 '16 at 13:54
  • seems like I dont have other ways but only use custom attribute.I thought there might be a hack for register_taxonomy – jameshwart lopez Jun 02 '16 at 14:28
  • I don't think this works in WC 3+ anymore. It does register a Taxonomy, but doesn't link it to WC Attributes. – ggedde Nov 17 '20 at 21:45
  • @ggedde well it is 5 years old. :) Looking at `wc_get_attribute_taxonomies()` I believe attribute taxonomies are stored in the `{$wpdb->prefix}woocommerce_attribute_taxonomies` and can be filtered via [`woocommerce_attribute_taxonomies`](https://github.com/woocommerce/woocommerce/blob/02cf0dfaed5923513de0c88add597d1560c2cfd2/includes/wc-attribute-functions.php#L73). Looks like LoicTheAztec has the insert row into the attributes table covered in his answer, but it appears that you can call `wc_create_attribute()` instead of duplicating the function. – helgatheviking Nov 18 '20 at 16:52
  • I was not able to insert an attribute by filtering `woocommerce_attribute_taxonomies` since other areas of Woo need this to have an ID that exists in the database table. – helgatheviking Nov 18 '20 at 17:04
  • @helgatheviking can I create a new `taxonomy` attribute for products and then attach it to all existing products directly with `SQL QUERY`? – Saad Abbasi Nov 25 '20 at 11:04
  • Probably? I believer everything is possible given enough time/resources! don't know _how_ to do that though myself. – helgatheviking Nov 27 '20 at 16:16
8

For Woocommerce 3+ (2018)

To create a new product attribute from a label name use the following function:

function create_product_attribute( $label_name ){
    global $wpdb;

    $slug = sanitize_title( $label_name );

    if ( strlen( $slug ) >= 28 ) {
        return new WP_Error( 'invalid_product_attribute_slug_too_long', sprintf( __( 'Name "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) );
    } elseif ( wc_check_if_attribute_name_is_reserved( $slug ) ) {
        return new WP_Error( 'invalid_product_attribute_slug_reserved_name', sprintf( __( 'Name "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) );
    } elseif ( taxonomy_exists( wc_attribute_taxonomy_name( $label_name ) ) ) {
        return new WP_Error( 'invalid_product_attribute_slug_already_exists', sprintf( __( 'Name "%s" is already in use. Change it, please.', 'woocommerce' ), $label_name ), array( 'status' => 400 ) );
    }

    $data = array(
        'attribute_label'   => $label_name,
        'attribute_name'    => $slug,
        'attribute_type'    => 'select',
        'attribute_orderby' => 'menu_order',
        'attribute_public'  => 0, // Enable archives ==> true (or 1)
    );

    $results = $wpdb->insert( "{$wpdb->prefix}woocommerce_attribute_taxonomies", $data );

    if ( is_wp_error( $results ) ) {
        return new WP_Error( 'cannot_create_attribute', $results->get_error_message(), array( 'status' => 400 ) );
    }

    $id = $wpdb->insert_id;

    do_action('woocommerce_attribute_added', $id, $data);

    wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );

    delete_transient('wc_attribute_taxonomies');
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.


Based on:

Related: Create programmatically a product using CRUD methods in Woocommerce 3

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • 1
    Seems to keep creating duplicate taxonomies for me. Seems like the `taxonomy_exists` check is not working. – ggedde Nov 17 '20 at 22:13