Cum să creezi taxonomii personalizate pentru atribute WooCommerce dintr-un plugin
Am creat un plugin pentru importul de produse în WordPress cu WooCommerce. Funcționează bine, cu excepția atributelor produselor - nu reușesc să le import corect.
Problema este că la produse adaug taxonomii personalizate care nu sunt definite în panoul de administrare. În mod surprinzător, nu găsesc o metodă pentru asta. Am încercat wp_insert_term()
cu register_taxonomy()
, dar acestea nu adaugă nimic în tabelul wp_woocommerce_attribute_taxonomies
din baza de date și nu le găsesc nici în atributele produsului, nici în pagina de atribute din dashboard. Le-am găsit doar în tabelul wp_terms
, dar din câte am înțeles, acolo nu ar trebui să fie stocate atributele de produs WooCommerce.
update_post_meta()
de asemenea nu pare să funcționeze (poate adăuga atribute ca meta, dar eu am nevoie de ele ca atribute de produs WooCommerce).
Trebuie să creez atribute dacă nu există înainte de a importa produsele. Există vreo funcție pentru asta pe care am omis-o?
Nu sunt sigur dacă ar trebui să postez ce am făcut până acum, dar iată codul relevant pentru această problemă:
// Acesta este un exemplu de ce primesc de la input-ul AJAX
$product_attributes = array(
"attr_id_01" => array(
"name" => "Material",
"value" => "Metal",
"is_visible" => 1,
"is_taxonomy" => 1
),
"attr_id_02" => array(
"name" => "Tip",
"value" => "Are mâner",
"is_visible" => 1,
"is_taxonomy" => 1
)
);
foreach ($product_attributes_copy as $key => $value) {
// Filtrul sanitize_title este furnizat de pluginul CyrToLat,
// practic transformă șirul într-unul prietenos pentru URL-uri,
// este folosit pentru că numele și valorile pot conține chirilice, majuscule și spații
$filtered_name = apply_filters('sanitize_title', $value['name']);
$filtered_value = apply_filters('sanitize_title', $value['value']);
$taxonomy = 'pa_' . $filtered_name;
$parent_term = term_exists( $filtered_value, $taxonomy );
$parent_term_id = $parent_term['term_id'];
if ( ! taxonomy_exists($taxonomy) ) {
register_taxonomy($taxonomy, 'product', array('label' => $value['name']) );
}
// Nu primesc erori de la următorul cod
$insert_result = wp_insert_term(
$filtered_value,
$taxonomy,
array(
'description'=> '',
'slug' => $filtered_value,
'parent'=> $parent_term_id
)
);
}

Din anumite motive, WooCommerce nu pare să vrea să faci acest lucru. Nu sunt sigur de ce, deoarece a cere să fie făcut manual este o problemă pentru scalabilitate în numeroase cazuri (ca să nu mai vorbim că, dacă ai atribute cu multe valori posibile, interfața pe care o oferă se încarcă foarte încet). După ce am săpat puțin, iată funcțiile private pe care le folosesc paginile de administrare, modificate pentru apelare sistematică.
function process_add_attribute($attribute)
{
global $wpdb;
// check_admin_referer( 'woocommerce-add-new_attribute' );
if (empty($attribute['attribute_type'])) { $attribute['attribute_type'] = 'text';}
if (empty($attribute['attribute_orderby'])) { $attribute['attribute_orderby'] = 'menu_order';}
if (empty($attribute['attribute_public'])) { $attribute['attribute_public'] = 0;}
if ( empty( $attribute['attribute_name'] ) || empty( $attribute['attribute_label'] ) ) {
return new WP_Error( 'error', __( 'Vă rugăm, furnizați un nume de atribut și un slug.', 'woocommerce' ) );
} elseif ( ( $valid_attribute_name = valid_attribute_name( $attribute['attribute_name'] ) ) && is_wp_error( $valid_attribute_name ) ) {
return $valid_attribute_name;
} elseif ( taxonomy_exists( wc_attribute_taxonomy_name( $attribute['attribute_name'] ) ) ) {
return new WP_Error( 'error', sprintf( __( 'Slug-ul "%s" este deja folosit. Schimbați-l, vă rugăm.', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) );
}
$wpdb->insert( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute );
do_action( 'woocommerce_attribute_added', $wpdb->insert_id, $attribute );
flush_rewrite_rules();
delete_transient( 'wc_attribute_taxonomies' );
return true;
}
function valid_attribute_name( $attribute_name ) {
if ( strlen( $attribute_name ) >= 28 ) {
return new WP_Error( 'error', sprintf( __( 'Slug-ul "%s" este prea lung (maximum 28 de caractere). Scurtați-l, vă rugăm.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
} elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
return new WP_Error( 'error', sprintf( __( 'Slug-ul "%s" nu este permis deoarece este un termen rezervat. Schimbați-l, vă rugăm.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
}
return true;
}
Apelat astfel:
$insert = proccess_add_attribute(array('attribute_name' => 'my-new-slug', 'attribute_label' => 'my-new-attribute', 'attribute_type' => 'text', 'attribute_orderby' => 'menu_order', 'attribute_public' => false));
if (is_wp_error($insert)) { do_something_for_error($insert); }
Câmpurile asociate cu atributul sunt numele (slug standard wp), eticheta (versiune ușor de înțeles a numelui atributului), tipul (ai de ales între 'select' și 'text', dar dacă creezi sistematic, probabil vei dori text - am modificat funcția să folosească implicit această valoare), public (etichetat ca "Activează arhivele" în interfață, am făcut funcția să folosească implicit valoarea din interfață) și orderby (opțiunile sunt 'menu_order' (denumit "Ordonare personalizată" în interfață), 'name' (explicativ), 'name_num' (nume numeric) și 'id' (ID-ul termenului))

Am rezolvat problema diferit, dar nu am postat soluția aici pentru că nu este suficient de generică și nici atât de elegantă pe cât mi-aș fi dorit (dar se pare că nu există o soluție elegantă pentru asta în WooCommerce...). Cred că codul tău ar trebui să funcționeze și eu, așa că îl voi marca ca răspuns. Și mulțumesc pentru efortul depus și explicațiile!
