Вопрос или проблема
У меня есть следующие функции для создания глобального атрибута продукта и заполнения его терминами на основе данных из 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;
}
Теперь в моем цикле обработки данных я пробую таким образом создать атрибут, если он не существует, и то же самое для каждого термина в этом атрибуте.
Наконец, я пытаюсь добавить их к продукту.
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;
}
}
Теперь моя проблема здесь в том, что мне нужно запускать один и тот же фрагмент кода несколько раз, чтобы на самом деле получить результат, и я не уверен, почему. Обычно при первом запуске я сталкиваюсь с ошибкой
Неверная таксономия
Во время выполнения wp_insert_term
, что вместо создания WP_Term
приводит к WP_Error
Однако если я запускаю его несколько раз, все в конечном итоге создается.
Я не уверен, что здесь происходит.
Я пытался очистить кэши термов и таксономий на случай, если это было неудачно из-за кэша, но безуспешно.
Позвольте мне добавить немного информации, например, переменную $attribute
перед вызовом функции getOrCreateTerm
И результат taxonomy_exists
показывает false во время wp_insert_term
, даже если он был четко определен ранее и имеет ID
В конце я добавил быструю проверку с
taxonomy_exists($slug)
и если он не существует перед добавлением терминов, я использую
register_taxonomy($taxonomySlug, 'product')
Это, похоже, позволило создать все термины за один раз.
Ответ или решение
Когда вы работаете с продуктами в WooCommerce и взаимодействуете с глобальными атрибутами и терминами, вам может понадобиться создавать атрибуты и добавлять термины к ним в одном цикле, однако возникают сложности, такие как ошибочное сообщение "Invalid taxonomy". Давайте рассмотрим вашу ситуацию более подробно и проанализируем, как можно оптимизировать процесс.
Проблема: Ошибка "Invalid taxonomy"
Ошибка "Invalid taxonomy" возникает во время выполнения функции wp_insert_term
, когда система не может распознать таксономию, к которой вы пытаетесь добавить термин. Это может происходить по нескольким причинам:
-
Кэширование: Кэширование может временно хранить устаревшую информацию о таксономиях. Вы уже пробовали очищать кэш таксономий и терминов, но это может быть недостаточно.
-
Регистрация таксономий: Таксономия может не быть зарегистрирована к моменту, когда выполняется код добавления термина. Если при проверке с помощью
taxonomy_exists
возвращается FALSE, это говорит о том, что таксономия еще не была зарегистрирована.
Решение проблемы
Вы нашли временное решение, добавив проверку с помощью taxonomy_exists($slug)
и вызвав register_taxonomy($taxonomySlug, 'product')
, если таксономия не существует. Это действительно устранит проблему с регистрацией термина, так как register_taxonomy
гарантирует, что таксономия будет зарегистрирована перед тем, как вы попытаетесь добавить к ней термины.
Пример кода
Вот как вы можете оптимизировать вашу логику:
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);
// Если таксономия не существует, регистрируем её
if (!taxonomy_exists($taxonomySlug)) {
register_taxonomy($taxonomySlug, 'product');
}
// Добавляем новый термин
/** @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;
}
Итог
С учетом ваших изменений и добавления дополнительных проверок, процесс создания атрибутов и терминов должен быть более надежным. Теперь в случае отсутствия зарегистрированной таксономии она будет создана, и вы сможете успешно добавить термины, не сталкиваясь с ошибками.
Также важно убедиться, что вы вызываете функции в правильном порядке и правильно обрабатываете ошибки. Пробежавшись по коду, вы можете убедиться, что все проверки выполняются до операций, которые могут быть причиной возникновения ошибок.
Эта оптимизация позволила динамически и эффективно управлять атрибутами продуктов, что существенно упрощает обработку данных и интеграцию с API.