Attribuut-taxonomieën (WooCommerce)
WooCommerce's Attributes (Kenmerken) zijn een instantie van het WordPress Categorie-taxonomische systeem, bedoeld voor ontsluiting van producten op basis van intrinsieke eigenschappen (bv. maat & kleur als het om kleding gaat).
Attibutes komen in twee smaken:
- Predefined Attributes
- Custom Attributes.
Dit hoofdstuk gaat voornamelijk over deze eerste variant.
Database-tabellen
wp_woocommerce_attribute_taxonomies
Tabel wp_woocommerce_attribute_taxonomies
bevat alleen beschrijvingen van de taxonomieën. Da's ca. hetzelfde als de 'hoofd-taxons'. Voorbeeld:
SELECT * FROM kbo3.wp_woocommerce_attribute_taxonomies; attribute_id attribute_name attribute_label attribute_type attribute_orderby attribute_public ------------ -------------- ----------------- -------------- ----------------- ---------------- 5 breedte Breedte text name_num 1 6 diepte Diepte text name_num 1 7 lengte Lengte text name_num 1 8 automatische_stop Automatische stop text name 1
wp_terms
Subtaxons verschijnen gewoon in wp_terms
. Dat maakt het gemakkelijk om met subtaxons te werken, want het werkt hetzelfde als voor gewone categorieën.
wp_term_taxonomy
Tabel wp_term_taxonomy
verbindt taxons met taxonomieën. Hier kun je zien dat WooCommerce 'onder water' losse taxonomieën defineert voor alle attributen. Je herkent ze aan de prefix pa_
. Merk op dat parent=0
: Er wordt niet gebruik gemaakt van hierarchie! Ook niet zo vreemd, omdat je bij attributen max. twee lagen hebt. Voorbeeld:
SELECT * FROM kbo3.wp_term_taxonomy where taxonomy like "pa_%"; term_taxonomy_id term_id taxonomy description parent count ---------------- ------- ---------- ------------- ------ ----- 110 110 pa_breedte Breedte-taxon 0 0
wp_term_relationships
Tabel wp_term_relationships
verbindt taxons met WordPress-objecten.
wp_termmeta
Tabel wp_termmeta
lijkt metadata te bevatten: Als je nog iets extra's kwijt wilt over een taxon, kun je dat hier doen. WooCommerce maakt hier bv. voor product_cat-taxonomieën aan, om de count per hoofdtaxon in op te slaan.
Het lijkt vooralsnog niet gebruikt te worden voor attribuut-taxonomieën.
Database-velden
In het algemeen zijn veldnamen binnen een WordPress-instantie niet consistent. Dat kun je zien aan het ER-diagram elders in dit artikel:
- In tabel wp_users heet de pk ID
- In tabel wp_usermeta heet dit veld user_id
- In tabel wp_posts heet dit veld post_author.
Desalniettemin: Rondom taxonomieën lijken veldnamen consistent te zijn. Anders had dit hoofdstuk weinig zin.
term_id
term_id
is de pk voor een taxon of term.
term_taxonomy_id
term_taxonomy_id
is de pk van de tussentabelwp_term_taxonomy
, die ervoor zorgt dat je een many-to-many-relatie hebt tussenterms
enterm_relationships
- Zo'n veel-veel-relatie ben ik tot op heden nog niet tegengekomen. Vandaar dat deze twee velden steeds dezelfde waardes lijken te hebben: Er zijn dan evenveel records in beide tabellen
- Overigens: Ik heb geen idee waarom je zo'n veel-veel-relatie wilt hebben, maar daar gaat het nu niet om.
UI-Velden
Dit zijn de velden die ik zoal in de user interface tegenkom. Namen zijn inconsistent en niet-intuïtief
Name - attribute_name
Shown on the front-end
Slug - attribute_label
Max. 28 karakters.
attribute_type
Het soort control dat gebruikt wordt als interface??? Bv.:
select
- Beperkt aantal keuzes, zoals een lookup-tabel of voor Boolese waardentext
- Tekstveld, lijkt me.
Enable Archives
Dus dat je een 'taxon-pagina' hebt. Altijd doen. Voor Attributes-taxonomieën kun je helaas geen afbeelding of tekst toevoegen (itt. gewone Categorieën) [1]
Custom ordering - attribute_orderby
Niet zo spannend:
menu_order
name
- etc.
attribute_public
Taxonomieën worden binnen een WordPress-site veelvuldig gebruikt voor interne aangelegenheden. Bv. om vertalingen bij te houden. Vandaar dat je er voor kunt kiezen om attribuut-taxonomieën verborgen te houden voor gebruikers.
Taxonomie toevoegen
Met taxonomie bedoel ik hier hetzelfde als hoofdtaxon .
Toevoegen van een hoofdtaxon/taxonomie, wil niet lukken met bv. wp_insert_term
. Aangezien Attributes een speciaal geval is van een categorie, zou je verwachten dat dit werkt. Maar dat doet het niet. Gelukkig kun je dit op een meer low-level fixen mbv. $wpdb
. Daar gebruik ik deze functies voor. Deze staat in één van m'n libraries (niet in functions.php
). Geïnspireerd op [2]:
function dvb_add_attribute_taxonomy($attribute) { # Add a WooCommerce Attribute-taxonomy ####################################################################################################### # # * Somehow, the usual function register_taxonomy doesn't work for WooCommerce Attributes, hence the # lower-level approach in this function # * Based on the example https://wordpress.stackexchange.com/questions/244335/creating-custom-woocommerce-attribute-taxonomies-from-a-plugin # * Jeroen Strompf, De Vliegende Brigade - April 2019 # * To be included in functions.php where appropriate ####################################################################################################### # Get acces to $wpdb class ####################################################################################################### # global $wpdb; ####################################################################################################### # Verify input ####################################################################################################### # 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', __( 'Attribute name and/and slug is missing.', 'woocommerce' ) ); } elseif ( ( $valid_attribute_name = dvb_check_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 "%s" already in use', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) ); } ####################################################################################################### # Insert into WordPress ####################################################################################################### # $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 dvb_check_attribute_name( $attribute_name ) { # Check if a given attribute name is valid ####################################################################################################### # # * Based on the example https://wordpress.stackexchange.com/questions/244335/creating-custom-woocommerce-attribute-taxonomies-from-a-plugin # * Jeroen Strompf, De Vliegende Brigade - April 2019 # * To be included in functions.php where appropriate if ( strlen( $attribute_name ) >= 28 ) { return new WP_Error( 'error', sprintf( __( 'Slug "%s" is longer than 28 characters)', 'woocommerce' ), sanitize_title( $attribute_name ) ) ); } elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) { return new WP_Error( 'error', sprintf( __( 'Slug "%s" is not allowed because it is a reserved term.', 'woocommerce' ), sanitize_title( $attribute_name ) ) ); } return true; };
Voorbeeld van een aanroep:
<?php ############################################################### # Call require_once ############################################################### # # Functions "dvb_add_attribute_taxonomy" and # "dvb_check_attribute_name" have been included in functions.php. # They become available through this "require_once" command # require_once("/home/strompf/www/example.com/wp-load.php"); ############################################################### # Define new attribute-taxonomy ############################################################### # $attribute_definition = array ( 'attribute_name' => 'attribute-naam (2)', 'attribute_label' => 'attribute-plakker (2)', 'attribute_type' => 'text', 'attribute_orderby' => 'menu_order', 'attribute_public' => false ); ############################################################### # Create this new attribute-taxonomy ############################################################### # dvb_add_attribute_taxonomy($attribute_definition);
Subtaxons toevoegen
- Attribuut-taxonomieën zijn niet-hiërarchisch, en zitten iets anders in elkaar dan product_cat-taxonomieën:
- Subtaxons toevoegen, gaat op dezelfde manier als voor product_cat-taxonomieën, met één verschil: De naam van de taxonomie, is de naam, voorafgegaan door
pa_
- De gebruikelijke API-functie hiervoor:
wp_insert_term
Voorbeeld uit een SQL-script, waarbij pa_breedte
de betreffende taxonomie is:
# Create table ############## # create table dim1_taxons_tmp select distinct dim1, concat ( "wp_insert_term('", replace(dim1, ".", ","),"'", ", 'pa_breedte',", " array('description' => 'Alle koolborstels met een breedte van ",replace(dim1, ".", ",")," mm',", " 'parent' => 0, 'slug' => 'breedte-",replace(dim1, "," ,""),"' ));" ) as dim1_php from root_tmp;
Je weet de 'pa-naam' pas met zekerheid, nadat er subtaxons zijn aangemaakt. Dan vind je 'm terug met zoiets als dit (in SQL):
SELECT distinct taxonomy FROM example_com.wp_term_taxonomy;
Mochten er nog geen taxons zijn toegevoegd:
- Voeg er eentje handmatig toe, om het te testen
- Gebruik je gezond verstand om uit te vogelen wat de naam zou zijn.
Nog één voorbeeld:
<?php require_once("/var/www/kbo3.dvb/wp-load.php"); wp_insert_term ( 'Met automatische stop' , 'pa_automatische_stop', array ( 'description' => 'Alle koolborstels met automatische stop', 'parent' => 0, 'slug' => 'met-automatische-stop' ) ); wp_insert_term ( 'Zonder automatische stop' , 'pa_automatische_stop', array ( 'description' => 'Alle koolborstels zonder automatische stop', 'parent' => 0, 'slug' => 'zonder-automatische-stop' ) );
Verwijderen
Hoe kun je alle attribuut-taxonomieën compleet verwijderen? Dus inclusief hoofdtaxons, subtaxons, en koppelen met objecten? Voor een beetje serieuse site, is het geen optie om dit handmatig te doen, vandaar. Ik kwam geen kant-en-klare code tegen, dus lekker zelf doen!
Alles op z'n tijd
De uitdaging is, om de onderdelen in de juiste volgorde te verwijderen, zodat je weet wat-wat is. Als ik bv. terms als laatste verwijder, is er een kans dat ik niet meer weet bij welke taxonomie ze horen. Ik denk dat dit een prima volgorde is:
select * from wp_term_relationships; # Taxons <-> Objecten - Vroeg verwijderen select * from wp_termmeta; # Metadata <-> Taxons - Vroeg verwijderen select * from wp_term_taxonomy; # Taxons <-> Taxonomy - Laat verwijderen select * from wp_terms; # Taxons - Laat verwijderen select * from wp_woocommerce_attribute_taxonomies; # Hoofdtaxons - Als laatste verwijderen