Um gleich mit der Tür in’s Haus zu fallen:
Warum?
Weil nicht überprüft wird, ob die Taxonomy des Terms mit dem Objekt verknüpft ist.
Es wird zB nicht überprüft, ob eine Kategorie der eingebauten Taxonomy ‚category‘ mit dem Beitragposttype ‚Post‘ verbunden ist.
Ob es daher überhaupt erlaubt ist, zB einem Beitrag eine Kategorie zuzuweisen.
Trotzdem wird das Term zum Objekt gespeichert!!
Ok, das Beispiel ist recht sinnlos weil wir ja wissen, dass Beiträge ganz einfach in Kategorien eingereiht werden können. Das Beispiel dient nur der Veranschaulichung.
Viel interessanter wird es beim Zuweisen von Custom Taxonomy Terms, also den selbst erstellten „Tags“ und „Kategorien“.
wp_set_object_terms() überprüft nämlich nicht, ob der Beitrag den ich gerade „tagge“ auch wirklich mit der Custom Taxonomy verbunden ist.
Genau das wird problematisch, wenn man Geschäftslogik mit eigenen Kategorien oder Tags löst.
Denn ich kann mit wp_set_object_terms() zB eine Seite ohne Probleme (und ohne Fehlermeldung) out-of-the-box einen Tag oder eine Kategorie zuweisen.
Lösung:
Vor dem Speichern mit wp set object terms() einfach überprüfen, ob der „Post“ (also das Objekt) eh mit der entsprechenden Custom Taxonomy verknüpft ist.
Wie finde ich das heraus?
Lösung mit der globalen wp_taxonomies Variable:
global $wp_taxonomies; $alle_taxonomie_objekte = $wp_taxonomies; $zugewiesenen_taxonomien = $alle_taxonomie_objekte['category']->object_type; /* Array ( [0] => post [1] => my_custom_post_type_wpent ) */
Es gibt eine globale Variable, die alle Taxonomien mit den diversen Informationen bereithält. Wir sehen in diesem Beispiel, dass die normale WordPress Kategorie mit den Beiträgen (‚posts‘) und einem Custom Post Type (‚my_custom_post_type_wpent‘) verknüpft ist.
Aber eben nicht mit dem ‚Page‘ Post Type aka „Seiten“.
Lösung mit get_object_taxonomies()
Den oben beschriebenen Weg können wir abkürzen, wenn wir die Funktion get_object_taxonomies() verwenden. Damit wird genau das oben gezeigte Array geholt. Im WP Codex gibt es dafür ein schönes Beispiel:
$taxonomy_names = get_object_taxonomies( 'post' ); print_r( $taxonomy_names);
Gibt uns folgendes zurück:
Array ( [0] => category [1] => post_tag [2] => post_format )
Alternativ mit wp_get_object_terms()
Man könnte auch direkt mit wp_get_object_terms() alle Terms abfragen, die zu einem Post gehören.
wp_get_object_terms( 123, 'my_custom_taxonomy_wpent' );
Ist die Taxonomy (hier „my_custom_taxonomy_wpent“) nicht mit dem Post 123 verknüpft, wird ein wp_error zurückgegeben.
Als Fehlermeldung bekommt man den Hinweis „invalid_taxonomy“ zurück und kann darauf reagieren.
Wie kommt es dazu?
Die Funktion wp_set_object_terms() ist in der Datei „taxonomy.php“ enthalten.
Es wird überprüft ob der übergebene Term existiert:
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2991
if ( !$term_info = term_exists($term, $taxonomy) ) {
Schauen wir uns die Funktion weiter näher an so sehen wir, dass zweimal die Funktion wp_get_object_terms() aufgerufen wird.
Diese Funktion liefert in unserem Fall ja einen Fehler zurück. Doch leider zu spät, da das Term schon gespeichert wurde. Außerdem wird gar nicht auf wp_error überprüft.
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2979
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L3051
In beiden Fällen bekommt jetzt eine Variable ein wp_error Objekt zugewiesen. Keine der Variablen wird auf diesen Umstand hin überprüft.
Die Speicherung eines Terms, der eigentlich gar nicht mit einem Objekt (Post, Page, CPT) über die Taxonomy verknüpft ist, geht problemlos über die Bühne.
Informatives:
Check ob Term besteht
http://codex.wordpress.org/Function_Reference/term_exists
Check ob es die Taxonomy gibt
https://codex.wordpress.org/Function_Reference/taxonomy_exists
Holt alle Taxonomien eines Posts (Objektes)
http://codex.wordpress.org/Function_Reference/get_object_taxonomies
wp_set_object_terms() auf Github
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2950
wp_get_object_terms() im Codex
http://codex.wordpress.org/Function_Reference/wp_get_object_terms
wp_set_object_terms() im Codex
https://codex.wordpress.org/Function_Reference/wp_set_object_terms
Check ob der Post einen gewissen Term hat
http://codex.wordpress.org/Function_Reference/has_term