Cum să creezi taxonomii personalizate pentru atribute WooCommerce dintr-un plugin

28 oct. 2016, 23:25:33
Vizualizări: 17.5K
Voturi: 4

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
        )
    );
}
0
Toate răspunsurile la întrebare 1
1
10

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))

18 nov. 2016 22:44:49
Comentarii

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!

Dmitry Gamolin Dmitry Gamolin
19 nov. 2016 14:07:22