woocommerce offtopic - cannot create product attribute (taxonomy) and add terms on the same execution

admin2025-01-07  4

I have the following functions to create a global product attribute and populate it with terms based on data from an API.

protected function getOrCreateAttribute($slug, $name)
    {
        $taxonomyId = wc_attribute_taxonomy_id_by_name($slug);
        if (!empty($taxonomyId) && $taxonomyId > 0) {
            return $taxonomyId;
        }
        $taxonomyId = wc_create_attribute([
            'name' => $name,
            'slug' => $slug,
            'type' => 'select',
        ]);
        if ($taxonomyId instanceof \WP_Error) {
            throw new Exception($taxonomyId->get_error_message());
        }
        return $taxonomyId;
    }

    protected function getOrCreateTerm($slug, $name, $taxonomySlug)
    {
        $term = get_term_by('slug', $slug, $taxonomySlug);
        if ($term === false) {
            clean_taxonomy_cache($taxonomySlug);
            /** @var \WP_Term|\WP_Error $term */
            $term = wp_insert_term($name, $taxonomySlug, ['slug' => $slug]);
            clean_term_cache($term->term_id, $taxonomySlug);
        }
        if ($term instanceof \WP_Error) {
            throw new Exception($term->get_error_message());
        }
        return $term;
    }

Now in my data processing loop I'm trying this way to create an attribute if it doesn't exist, and the same for each term in that attribute.

Finally I'm trying to add them to the product.

            foreach ($featuresGroup->Features as $feature) {
                $taxonomyName = $feature->Feature->Name->Value;
                $taxonomySlug = $this->slugger->slugify($taxonomyName);
                $taxonomyId = $this->getOrCreateAttribute($taxonomySlug, $taxonomyName);
                $attribute = wc_get_attribute($taxonomyId);

                $termsToSet = [];
                $termName = $feature->PresentationValue;
                $termSlug = $this->slugger->slugify($termName);
                $term = $this->getOrCreateTerm($termSlug, $termName, $attribute->slug);

                $termsToSet[] = $term->term_id;
                if (array_key_exists($attribute->slug, $productAttributes)) {
                    $productAttribute = &$productAttributes[$attribute->slug];
                    $productAttribute->set_options($termsToSet);
                } else {
                    $wcProductAttribute = new \WC_Product_Attribute();
                    $wcProductAttribute->set_name($attribute->name);
                    $wcProductAttribute->set_id($attribute->id);
                    $wcProductAttribute->set_visible(1);
                    $wcProductAttribute->set_options($termsToSet);
                    $productAttributes[$attribute->slug] = $wcProductAttribute;
                }
            }

Now my problem here is that I have to run the same piece of code multiple times to actually get a result and I'm not sure why. Normally on the first run I'm encountering an error

Invalid taxonomy

During the wp_insert_term execution which instead of creating the WP_Term produces a WP_Error

However if I run it multiple times, everything eventually gets generated.

I'm not sure what's going on here.

I've tried clearing the caches for terms and taxonomies in case it was failing due to cache, to no avail.

Let me add some info for example the $attribute variable before getOrCreateTerm function call

And the result of taxonomy_exists shows false during wp_insert_term even though it was clearly defined before and has an ID

I have the following functions to create a global product attribute and populate it with terms based on data from an API.

protected function getOrCreateAttribute($slug, $name)
    {
        $taxonomyId = wc_attribute_taxonomy_id_by_name($slug);
        if (!empty($taxonomyId) && $taxonomyId > 0) {
            return $taxonomyId;
        }
        $taxonomyId = wc_create_attribute([
            'name' => $name,
            'slug' => $slug,
            'type' => 'select',
        ]);
        if ($taxonomyId instanceof \WP_Error) {
            throw new Exception($taxonomyId->get_error_message());
        }
        return $taxonomyId;
    }

    protected function getOrCreateTerm($slug, $name, $taxonomySlug)
    {
        $term = get_term_by('slug', $slug, $taxonomySlug);
        if ($term === false) {
            clean_taxonomy_cache($taxonomySlug);
            /** @var \WP_Term|\WP_Error $term */
            $term = wp_insert_term($name, $taxonomySlug, ['slug' => $slug]);
            clean_term_cache($term->term_id, $taxonomySlug);
        }
        if ($term instanceof \WP_Error) {
            throw new Exception($term->get_error_message());
        }
        return $term;
    }

Now in my data processing loop I'm trying this way to create an attribute if it doesn't exist, and the same for each term in that attribute.

Finally I'm trying to add them to the product.

            foreach ($featuresGroup->Features as $feature) {
                $taxonomyName = $feature->Feature->Name->Value;
                $taxonomySlug = $this->slugger->slugify($taxonomyName);
                $taxonomyId = $this->getOrCreateAttribute($taxonomySlug, $taxonomyName);
                $attribute = wc_get_attribute($taxonomyId);

                $termsToSet = [];
                $termName = $feature->PresentationValue;
                $termSlug = $this->slugger->slugify($termName);
                $term = $this->getOrCreateTerm($termSlug, $termName, $attribute->slug);

                $termsToSet[] = $term->term_id;
                if (array_key_exists($attribute->slug, $productAttributes)) {
                    $productAttribute = &$productAttributes[$attribute->slug];
                    $productAttribute->set_options($termsToSet);
                } else {
                    $wcProductAttribute = new \WC_Product_Attribute();
                    $wcProductAttribute->set_name($attribute->name);
                    $wcProductAttribute->set_id($attribute->id);
                    $wcProductAttribute->set_visible(1);
                    $wcProductAttribute->set_options($termsToSet);
                    $productAttributes[$attribute->slug] = $wcProductAttribute;
                }
            }

Now my problem here is that I have to run the same piece of code multiple times to actually get a result and I'm not sure why. Normally on the first run I'm encountering an error

Invalid taxonomy

During the wp_insert_term execution which instead of creating the WP_Term produces a WP_Error

However if I run it multiple times, everything eventually gets generated.

I'm not sure what's going on here.

I've tried clearing the caches for terms and taxonomies in case it was failing due to cache, to no avail.

Let me add some info for example the $attribute variable before getOrCreateTerm function call

And the result of taxonomy_exists shows false during wp_insert_term even though it was clearly defined before and has an ID

Share Improve this question edited Nov 7, 2022 at 0:15 gabtzi asked Nov 7, 2022 at 0:07 gabtzigabtzi 1011 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

In the end I added a quick check with

taxonomy_exists($slug)

and if it doesn't exist before adding the terms I use

register_taxonomy($taxonomySlug, 'product')

This seems to have allowed creation of all terms in one go.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1736258166a493.html

最新回复(0)