Thứ Ba, 10 tháng 6, 2014

Specifying Depth for Hierarchical Vocabularies [Working with Taxonomy]

In the previous examples, weve 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. Heres the effect of changing the depth parameter of the
URLAll 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 were 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 hotaxonomies are stored in
the database. In a typical non-Drupal database, you might create a flataxonomy 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, an 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

Lets 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 followinmodule 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
*    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 objector 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 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 (tidvid, 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 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  = 2print_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 wha 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