In the previous examples, we’ve been using an implied parameter. For example, the URL
http://example.com/?q=taxonomy/term/5 is really http://example.com/?q=taxonomy/term/5/0
where the trailing 0 is the number of levels of hierarchy to search when preparing the result set for display; all would designate that all
levels should be included. Suppose you had the hierarchical vocabulary shown in Table 15-3.
Table 15-3. A Geographical Hierarchical Vocabulary
(Child Terms Are Indented Below Their Parent)
| |
Term ID
|
Name
|
1
|
Canada
|
2
|
British Columbia
|
3
|
Vancouver
|
4
|
Ontario
|
5
|
Toronto
|
The first level of hierarchy is the country, Canada; it has two children, the provinces British Columbia and Ontario. Each province has one child, a major Canadian city where Drupal development is rampant. Here’s the effect of changing the depth parameter of the
URL. All nodes tagged with Vancouver will share the following URL:
http://example.com?q=taxonomy/term/3 or http://example.com?q=taxonomy/term/3/0
To display all nodes tagged with British Columbia (but none tagged with Vancouver), use this URL:
http://example.com?q=taxonomy/term/2
The following URL applies to all nodes tagged with British Columbia and any British Columbian city (note that we’re setting the depth
to one level of hierarchy): http://example.com?q=taxonomy/term/2/1
Automatic RSS Feeds
Each term has an automatic RSS feed that displays the latest nodes tagged with that term. For example, the feed for term ID 3 is at
http://example.com/?q=taxonomy/term/3/feed
Storing Taxonomies
If you’re going to go beyond the built-in taxonomy capabilities, it’s imperative that you understand how taxonomies are stored in
the database. In a typical non-Drupal database, you might create a flat taxonomy by simply adding a column to a database table.
As you’ve seen, Drupal adds a taxonomy through normalized database tables. Figure 15-7 shows the table structures.
Figure 15-7. Drupal’s taxonomy tables.*vid in the taxonomy_term_data table refers to the version
ID in the node_revisions table, not to vocabulary ID.
The following tables make up Drupal’s taxonomy storage system:
• taxonomy_vocabulary: This table stores the information about a vocabulary that’s editable through Drupal’s Taxonomy interface.
• taxonomy_index: This table stores the relationships between nodes and taxonomy terms.
• taxonomy_term_data: This table contains the actual name of the term, which vocabulary it’s in, its optional description, and the
weight that determines its position in lists of terms presented tothe user for term selection (for example, on the node submit form).
• taxonomy_term_hierarchy: The taxonomy_term_hierarchy table contains the term ID of a term as well as the term ID of its
parent. If a term is at the root (that is, it has no parent), theID of the parent is 0.
• field_data_field_xxxxx: The table used to store related term information where xxxx is the name of the field defined for a
specific vocabulary.
Module-Based Vocabularies
In addition to the vocabularies that can be created using Admin -> Structure -> Taxonomy -> Add, modules can use the taxonomy
tables to store their own vocabularies. For example, the forum module uses the taxonomy tables to keep a vocabulary of containers
and forums.
The module that owns a vocabulary is identified in the module column of the taxonomy_vocabulary table. Normally, this column will contain taxonomy, because the taxonomy module manages most vocabularies.
Creating a Module-Based Vocabulary
Let’s look at an example of a module-based vocabulary. The Forums module uses taxonomy as a mechanism for organizing forum
topics. It creates its vocabulary program matically (see: modules/forum/forum.install), as shown in the following example, and
assumes owner ship of the vocabulary by setting the module key of the $vocabulary array to the module name (without .module).
// Create the forum vocabulary if it does not exist.
$vocabulary = taxonomy_vocabulary_load(variable_get('forum_nav_vocabulary', 0)); if (!$vocabulary) {
$edit = array('name' => t('Forums'), 'machine_name' => 'forums','description' => t('Forum navigation vocabulary'),
'hierarchy' => 1,'module' => 'forum','weight' => -10,);
$vocabulary = (object) $edit; taxonomy_vocabulary_save($vocabulary); variable_set('forum_nav_vocabulary',
$vocabulary->vid);
}
Keeping Informed of Vocabulary Changes with Taxonomy Hooks
If you do keep a vocabulary for your own module, you’ll want to be informed of any changes that are made to the vocabulary
through the standard Taxonomy user interface. You might also want to be informed when a change is made to an existing vocabulary maintained by taxonomy.module. In either case, you can be informed of changes to vocabularies by implementing taxonomy hooks.
The following module has an implementation of taxonomy hooks thatkeeps you informed of vocabulary changes by e- mail. Here’s the taxonomymonitor.info file:
name = Taxonomy Monitor
description = Sends email to notify of changes to taxonomy vocabularies.
package = Pro Drupal Development dependencies[] = taxonomy
core = 7.x
files[] = taxonomymonitor.module
Here’s taxonomymonitor.module:
<?php
/**
* @file
* A module that emails a person when taxonomy changes
*/
/**
* Implements hook_term_insert()
*/
function taxonomymonitor_term_insert($term) {
_send_notification('term', 'added', $term->name);
}
/**
* Implements hook_term_update()
*/
function taxonomymonitor_term_update($term) {
_send_notification('term', 'updated', $term->name);}
/**
* Implements hook_term_delete()
*/
function taxonomymonitor_term_delete($term) {_send_notification('term', 'deleted', $term->name);}
/**
* Implements hook_vocabulary_insert()
*/
function taxonomymonitor_vocabulary_insert($vocabulary) {
_send_notification('vocabulary', 'added', $vocabulary->name);}
/**
* Implements hook_vocabulary_update()
*/
function taxonomymonitor_vocabulary_update($vocabulary) {
_send_notification('vocabulary', 'updated', $vocabulary->name);}
/**
* Implements hook_vocabulary_delete()
*/
function taxonomymonitor_vocabulary_delete($vocabulary) {
_send_notification('vocabulary', 'deleted', $vocabulary->name);}
/**
* Log changes to taxonomy using watchdog and send out an email notification
* describing the change
*/
function _send_notification($type, $action, $name) {
watchdog('Taxonomy Monitor', 'A @type named @name was @action', array('@type' => $type, '@name' => $name, '@action'=> $action))$to = variable_get('site_mail','');
$subject = t("There was a change to taxonomy");
$body = t("A $type named $name was $action");
// Send email here.}
For extra bonus points, you could modify the module to include the name of the user who made the change.
Common Tasks
Here are some common tasks you may encounter when working with taxonomies.
Displaying Taxonomy Terms Associated with a Node
Taxonomy terms in Drupal 7 are essentially just fields attached to the node. To get the value of the taxonomy terms you must first
know a little bit about the content type associated with the node you are looking at, specifically the name of the field used tostore the taxonomy terms. As an example, I’ll use an Article that I created and assigned tags to. After creating the node and capturing the node ID of the new node (in my example it was 2), I could display the taxonomy terms associated with this node using the following code
snippet. I’ll paste the snippet into a new block, set the input format to PHP code, and assign the block to a region on my page.
<?php
/**
* Display the taxonomy terms associated with a given node
*/
$nid = 2;
$node = node_load($nid);
$result = field_view_field('node', $node, 'field_tags', array('default')); print render($resul);
In the foregoing code, I’m calling the field_view_field() function, passing the type of entity that contains the field (a node), the object containing the field (the node object that I’ve loaded), the name of the field (field_geographic_location), and the display mode (default)
Building Your Own Taxonomy Queries
If you need to generate a node listing of some sort, you might end up wishing that things were simpler; you might wish that Drupal
kept taxonomy terms in the node table, so you could say the following:
SELECT * FROM node WHERE vocabulary = 1 and term = 'cheeseburger'
The cost of flexibility is a bit more work for the Drupal developer. Instead of making simple queries such as this, you must learn to
query the taxonomy tables using JOINs.
Using taxonomy_select_nodes()
Before you start writing a query, consider whether you can get what you want using an existing function. For example, if you want titles of nodes tagged by term IDs 5 and 6, you can use taxonomy_ select_nodes():
$tids = array(5, 6);
$result = taxonomy_select_nodes($tids);
$titles = array(); foreach($result as $nid) {
$node = node_load($nid);
$titles[] = $node->title;
}
Taxonomy Functions
The following sections explain functions that might be useful for your module.
Retrieving Information About Vocabularies
The built-in functions in the following sections retrieve information about vocabularies, as vocabulary data objects or as
an array of such objects.
taxonomy_vocabulary_load($vid)
This function retrieves a single vocabulary (the $vid parameter is the vocabulary ID) and returns a vocabulary object. It also caches vocabulary objects internally, so multiple calls for the same vocabulary aren’t expensive. This function is also a special load functionfrom the point of view of Drupal’s menu system (see Chapter 4 for details). Since taxonomy vocabularies
are entities,the taxonomy_ vocabulary_load function is just a wrapper for the entity_load function.
taxonomy_get_vocabularies()
The taxonomy_get_vocabularies($type) function retrieves an array of all vocabulary objects.
Adding, Modifying, and Deleting Vocabularies
The following functions create, modify, and delete vocabularies. They return a status code that’s one of the Drupal
constants SAVED_UPDATED or SAVED_NEW.
taxonomy_vocabulary_save($vocabulary)
This function creates a new vocabulary or updates an existing one. The $vocabulary parameter is a vocabulary object containing the following keys:
• vid: The vocabulary ID
• name: The name of the vocabulary
• machine name: The internal Drupal name for this vocabulary
• description: The description of the vocabulary
• hierarchy: Set to 0 for no hierarchy, 1 for single hierarchy, and 2 for multiple hierarchy.
• module: The name of the module that’s responsible for this vocabulary; if this key is not passed, the value will default to taxonomy.
• weight: The weight of the vocabulary; it affects the placement of the node submission form in the Vocabularies
fieldset.
• rdf_mapping: An array that defines how terms are mapped
The taxonomy _vocabulary_save($vocabulary) function returns SAVED_NEW or SAVED_UPDATED.
taxonomy_vocabulary_delete($vid)
The $vid parameter of this function is the ID of the vocabulary. Deleting a vocabulary deletes all its terms by calling
taxonomy_del_term() for each term. The taxonomy_vocabulary_delete($vid) function returns SAVED_DELETED.
Retrieving Information About Terms
The built-in functions in the following sections retrieve information about terms, typically as objects or as an array of objects.
taxonomy_load_term($tid)
This function retrieves a term (the $tid parameter is the term ID) and returns a term object. It caches term objects internally, so multiple calls for the same term aren’t expensive. The structure of the term object looks like this:
$term = taxonomy _term_load(3); var_dump($term);
object(stdClass)#65 (9) { ["tid"]=> string(1) "3" ["vid"]=> string(1) "3
["name"]=> string(16) "British Columbia"
["description"]=> string(38) "A western province of stunning beauty." ["format"]=> string(1) "3"["weight"]=> string(1) "0"
["vocabulary_machine_name"]=> string(20) "geographic_locations"["field_related_term"]=> array(1) {
["und"]=> array(1) {
[0]=> array(1) {
["tid"]=> string(1) "2"}}}
["rdf_mapping"]=> array(5) { ["rdftype"]=>
array(1) {
[0]=> string(12) "skos:Concept"}
["name"]=> array(1) { ["predicates"]=>
array(2) {
[0]=> string(10) "rdfs:label" [1]=>
string(14) "skos:prefLabel"}}
["description"]=>
array(1) { ["predicates"]=> array(1) {
[0]=> string(15) "skos:definition"}}
["vid"]=>
array(2) { ["predicates"]=> array(1) {
[0]=> string(13) "skos:inScheme"}
["type"]=> string(3) "rel"
}
["parent"]=> array(2) { ["predicates"]=> array(1) {
[0]=> string(12) "skos:broader"}["type"]=> string(3) "rel"}}}
taxonomy_get_term_by_name($name)
The taxonomy_get_term_by_name($name) function searches for terms matching a string (the $name parameter is a string). White
space is stripped from $name, and matches are case insensitive. This function returns an array of term objects.
Adding, Modifying, and Deleting Terms
The following functions create, modify, and delete terms. They return a status code that is one of the Drupal constants SAVED_
UPDATED, SAVED_NEW, or SAVED_DELETED.
taxonomy_term_save($term)
This function creates a new term or updates an existing term. The $term is a term object:
• name: The name of the term
• description: The description of the term; this value is unused by Drupal’s default user interface, but might be used by your module or other third-party modules.
• vid: The ID of the vocabulary to which this term belongs
• weight: The weight of this term; it affects the order in which terms are shown in term selection fields.
• relations: An optional array of term IDs to which this term is related
• parent: Can be a string representing the term ID of the parent term, an array containing either strings representing the term IDs of the parent terms, or a subarray containing strings representing the term IDs of the parent terms. Optional.
• vocabulary_machine_name: The machine name of the vocabulary associated with this term
• tid: The term ID; if this key isn’t passed, a new term will be created.
This function returns SAVED_NEW or SAVED_UPDATED.
taxonomy_term_delete($tid)
The taxonomy_term_delete($tid) function deletes a term; the $tid parameter is the term ID. If a term is in a hierarchical
vocabulary and has children, the children will be deleted as well, unless a child term has multiple parents.
Retrieving Information About Term Hierarchy
When you are working with hierarchical vocabularies, the functions in the following sections can come in handy.
taxonomy_get_parents($tid, $key)
This function finds the immediate parents of a term; the $tid parameter is the term ID. The $key parameter defaults to tid and is a column of the term_data table (tid, vid, name, description, weight). taxonomy_get_parents($tid, $key)
returns an associative array of term objects, keyed by $key.
taxonomy_get_parents_all($tid)
This function finds all ancestors of a term; the $tid parameter is the term ID. The function returns an array of term objects.
taxonomy_get_children($tid, $vid, $key)
The taxonomy_get_children($tid, $vid, $key) function finds all children of a term. The $tid parameter is the term ID. The$vid parameter is optional; if a vocabulary ID is passed, the children of the term will be restricted to that vocabulary (note that
this is onlyimportant for terms that have multiple parents in different vocabularies, a rare occurrence). The $key parameter
defaults to tid and is a column of the term_data table (tid, vid, name, description, weight). This function returns an
associative array of term objects,keyed by $key.
taxonomy_get_tree($vid, $parent, $max_depth, $load_entities = FALSE)
This function generates a hierarchical representation of a vocabulary. The $vid parameter is the vocabulary ID of the
vocabulary for which to generate the tree. You can specify the $parent parameter if you don’t want the entire
tree for a vocabulary and want only that part of the tree that exists under the term ID specified by $parent. The $max_
depth parameter is an integer indicating the number of levels of the tree to return, and it defaults to NULL, indicating all levelsThe $load_entities parameter will cause acomplete load of each term object if set to TRUE. This function returns an array
of term objects with depth and parent keys added. The depth key is an integer indicating the level of hierarchy at which the term exists in the tree, and the parents key is anarray of term IDs of a term’s parents. For example, let’s get the results for
the vocabulary shown in Table 15-3, which happens to be vocabulary ID 2:
$vid = 2; print_r($taxonomy_get_tree($vid));
The results follow:
Array ([0] => stdClass Object ( [tid] => 1[vid] => 2
[name] => Canada
[description] => A mari usque ad mare.
[format] => 3 [weight] => 0 [depth] => 0
[parents] => Array ( [0] => 0 ))
[1] => stdClass Object ( [tid] => 4
[vid] => 2
[name] => Ontario
[description] => Ut incepit fidelis sic permanet.
[format] => 3 [weight] => 0 [depth] => 1
[parents] => Array ( [0] => 1 ))
[2] => stdClass Object ( [tid] => 5
[vid] => 2
[name] => Toronto
[description] => Diversity Our Strength.
[weight] => 0 [depth] => 2 [parents] => Array ([0] => 4 ))
[3] => stdClass Object ( [tid] => 2
[vid] => 2
[name] => British Columbia [description] => Splendor sine occasu. [format] => 3
[weight] => 0 [depth] => 1
[parents] => Array ( [0] => 1 ))
[4] => stdClass Object ( [tid] => 3
[vid] => 2
[name] => Vancouver
[description] => By Land, Sea and Air We Prosper.
[format] => 3 [weight] => 0 [depth] => 2
[parents] => Array ( [0] => 2 )))
Finding Nodes with Certain Terms
Sometimes, you want to have an easy way to query which nodes have certain terms or output the results of such a query. The
taxonomy_select_nodes($tids, $pager, $limit, $order) helps you accomplish that goal. This function finds nodes that match conditions by building and executing a database query based on given parameters. It returns a resource identifier pointing to the query results. The
$tids parameter is an array of term IDs. The $limit parameter indicates the maximum number of nodes to find. Setting $limit to
FALSE returns all nodes (no limit). The $pager parameter is a Boolean value indicating whether resulting nodes will be used with a
pager, and it defaults to TRUE. You might set $pager to FALSE if you were generating an XML feed. The $orderparameter contains an associative array of conditions that will be applied to the SQL statement—for example, ‘t.created’ => ‘DESC’
will sort the results in descending order based on the date created.
If you’re searching for many terms, this function can be database-intensive.
Additional Resources
Many modules use taxonomy for everything from adding access control (http://drupal.org/ project/taxonomy_access), to dynamic
category browsing (http://drupal.org/project/ taxonomy_browser), to showing nodes that are related via taxonomy terms in ablock
(http://drupal.org/project/similarterms). The Drupal Handbook has more information about taxonomy at http://drupal.org/
handbook/modules/taxonomy. See also the list of taxonomy-related modules athttp://drupal.org/project/Modules/category/71.
You’re encouraged to try the views module, especially for theming of taxonomy listings (http://drupal.org/project/views).
Summary
After reading this chapter, you should be able to
• Understand what taxonomy is.
• Understand terms, vocabularies, and their different options.
• Differentiate between flat, hierarchical, and multiple hierarchical vocabularies.
• Construct URLs to do AND and OR searches of taxonomy terms.
• Construct URLs for RSS feeds of taxonomy terms and term combinations.
• Understand how taxonomies are stored.
• Know how to use vocabularies within your own module.
• Set up your module to receive notification of changes to taxonomies.

Không có nhận xét nào:
Đăng nhận xét