CakePHP Tags Plugin
- Downloads:
- 1361
- Version:
- 1.0.0.0
- Released on:
- 2010-02-16
- Issue Tracker
- Changelog
Subscribe
CakePHP Tags Plugin
The tags plugin includes the Taggable Behavior that allows you to simply tag everything. It saves all tags in a tags table and connects any kind of records to them through the tagged table. You can specify alternate tables for both in the case you get *A LOT* records tagged.
Requirements
CakePHP 1.3
Related Articles
No related articles were found.Documentation
Installation
Download a release.
Extract the tags plugin to the app/plugins directory in your application.
The standard directory name is tags.
Directory Structure
/app
/plugins
/datasources
/debug_kit
/localized
/tags (Same location as other plugins)
For more information on plugins and app structure, please see the Plugins section of the CakePHP Book.
Create tables
Update your database schema using one of the following command from your application root:
- Cake schema shell:
cake schema create app -plugin tags - Migrations plugin shell:
cake migration run all -plugin tags
Usage
To turn an existing model to a Taggable model, you only need to add the Tags.Taggable behavior to its Behavior lists.
var $actsAs = array(
'Tags.Taggable');
Once the Behavior is added to the Model it will:
Create a new HABTM relationship named Tag using the Tagged join class.
Tag the object with tags contained in the Model.tags field on each save. Note: The tags field can contain several tags separated with a comma.
Write the comma separated tag list in Model.tags field on each find() result.
If you need different settings for the Behavior, check the available options below.
Available options
Many Taggable behavior configurations are customizable. To change a setting, you must add its new value to the $actsAs attribute as detailed below. If you want further information about Behaviors please read the CakePHP Documentation related pages.
var $actsAs = array(
'Tags.Taggable' => array(
'separator' => '-',
'field' => 'tags',
'tagAlias' => 'Tag',
'tagClass' => 'Tags.Tag',
'taggedClass' => 'Tags.Tagged',
'foreignKey' => 'foreign_key',
'associationForeignKey' => 'tag_id',
'cacheWeight' => true,
'automaticTagging' => true,
'unsetInAfterFind' => false,
'resetBinding' => false)
);
The configuration above contains the default values for each setting. Here are some explanations:
- separator: string used to separate tags in the Model.tags value. (Default: ',')
- field: name of the Model field containing the tag list. (Default: 'tags')
- tagAlias: alias for the HABTM relationship between your Model and Tag. (Default: 'Tag')
- tagClass: name of the model representing Tags. (Default: 'Tags.Tag')
- taggedClass: name of the HABTM join model. (Default: 'Tags.Tagged')
- foreignKey: name of the HABTM join model field containing the foreign key to the Tagable model. (Default: 'foreign_key')
- associationForeignKey: name of the HABTM join model field containing the foreign key to the Tag model. (Default: 'tag_id')
- automaticTagging: whether or not the behavior will automatically call saveTags() after each save. (Default: 'tag_id')
- unsetInAfterFind: whether or not the related Tag entries have to be unset after a find. If this value is true, the $data['Tag'] array will be unset and tags will only be available using the $data['Model']['tags'] value. (Default: false)
- resetBinding: value passed as the second param of to the bindModel() call when creating the HABTM association. If set to true, the binding will last only one query. (Default: false)
Note that the tagClass, taggedClass, foreignKey and associationForeignKey values must not be changed if you use the plugin as it is shipped. Use these settings when you want to use your own models / tables structure
This documentation is written with the default configuration values.
Add a "tags" input to your forms
After adding the Taggable behavior to your model, you will need to update your views or controller so the data you save() contains a tags field with the related tags (comma separated).
It might be as simple as:
echo $this->Form->input('tags');
Display the related tags
Now that your model is Taggable and your forms allow users to add tags to objects, you may want to display the related tags.
First, you need to ensure that the related HABTM Tag association is fetched in your find using the Containable behavior or the recursive model property.
Then you could display the tags using either the Model.tags field value (containing a comma separated list of related tags), or the related Tag model data. Here is a sample data array (Recipe acts as Tags.Taggable):
Array
(
[Recipe] => Array
(
[id] => 1
[name] => Recipe #1
[content] => Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
[created] => 2010-01-13 10:03:20
[modified] => 2010-01-13 10:23:45
[tags] => Dessert, Cake
)
[Tag] => Array
(
[0] => Array
(
[id] => 4b4d9121-459c-4abd-af4b-2f981380bfcb
[identifier] =>
[name] => Dessert
[keyname] => dessert
[weight] => 0
[created] => 2010-01-13 10:23:45
[modified] => 2010-01-13 10:23:45
[Tagged] => Array
(
[id] => 4b4d9121-cb54-4a9e-970d-2f981380bfcb
[foreign_key] => 1
[tag_id] => 4b4d9121-459c-4abd-af4b-2f981380bfcb
[model] => Recipe
[language] => en-us
[created] => 2010-01-13 10:23:45
[modified] => 2010-01-13 10:23:45
)
)
[1] => Array
(
[id] => 4b4d9121-fe58-4fe7-b65a-2f981380bfcb
[identifier] =>
[name] => Cake
[keyname] => cake
[weight] => 0
[created] => 2010-01-13 10:23:45
[modified] => 2010-01-13 10:23:45
[Tagged] => Array
(
[id] => 4b4d9121-f3ec-4a24-bb32-2f981380bfcb
[foreign_key] => 1
[tag_id] => 4b4d9121-fe58-4fe7-b65a-2f981380bfcb
[model] => Recipe
[language] => en-us
[created] => 2010-01-13 10:23:45
[modified] => 2010-01-13 10:23:45
)
)
)
)
Note: if the HABTM relationship is not included in the find, the Model.tags field will be set an empty string value
The TagCloud helper
Display a Tag cloud with the TagCloud helper.
A Tag cloud is a user friendly way to display a tag list to users. The Tags plugin is shipped with a helper permitting to generate a markup easily skinnable using CSS.
Basic use
Here are the necessary steps for displaying a tag cloud with some basic options.
Add the TagCloud helper to your controller
var $helpers = array('Tags.TagCloud');
In you controller action, get a list of tags and pass it to the view. The Tagged model contains a custom find method _findCloud() which retrieves all the tags and populates values.
Here is an example code from a RecipesController, where Recipe actsAs Tagable:
$this->set('tags', $this->Recipe->Tagged->find('cloud', array('limit' => 10)));
Call the display() helper method where you want to display the cloud. For instance:
<ul id="tagcloud">
<?php
echo $this->TagCloud->display($tags, array(
'before' => '<li size="%size%" class="tag">',
'after' => '</li>'));
?>
</ul>
Will generate a code like:
<ul id="tagcloud">
<li size="160" class="tag"><a href="/search/index/by:cake" id="tag-4b4d9121-fe58-4fe7-b65a-2f981380bfcb">Cake</a> </li>
<li size="80" class="tag"><a href="/search/index/by:starter" id="tag-4b4d933d-f578-4d05-b28e-34ae1380bfcb">Starter</a> </li>
<li size="80" class="tag"><a href="/search/index/by:chocolate" id="tag-4b4d933d-b700-440d-a898-34ae1380bfcb">Chocolate</a> </li>
<li size="80" class="tag"><a href="/search/index/by:dessert" id="tag-4b4d9121-459c-4abd-af4b-2f981380bfcb">Dessert</a> </li>
</ul>
What happened?
The helper generated links (with an unique DOM id tag-{id}) to the index action of a search controller, the tag keyname being passed as a named param. The %size% string from the *before* param was replaced with a number based on the tag weight.
Available options of the TagCloud helper
The second param for the display() method is an array of options. The available keys are:
- shuffle: true to shuffle the tag list, false to display them in the same order than passed. (Default: true)
- extract: Set::extract() compatible format string. Path to extract weight values from the
$tagsarray passed (first param). *(Default: '{n}.Tag.weight')* - before: string to be displayed before each generated link. "*%size%*" will be replaced with tag size calculated from the weight. *(Default: empty)*
- after: string to be displayed after each generated link. "*%size%*" will be replaced with tag size calculated from the weight. *(Default: empty)*
- maxSize: size of the heaviest tag. *(Default: '160')*
- minSize: size of the lightest tag. *(Default: '80')*
- url: an array containing the default url. *(Default: array('controller' => 'search'))*
- named: the named parameter used to send the tag keyname. *(Default: 'by')*
Find tagged objects
The Tagged model has a custom find('tagged') method to find or paginate objects tagged with a given tag.
Find usage examples
- To find all Articles having at least one Tag the call would be:
$this->Tagged->find('tagged', array('model' => 'Article'));
- To find all Articles tagged _cakephp_ the call would be:
$this->Tagged->find('tagged', array('by' => 'cakephp', 'model' => 'Article'));
h2. Pagination usage example
You can also use this custom find method with paginated results.
Below is a complete example of using the find('tagged') method with pagination to filter elements by tag:
function index() {
if (isset($this->passedArgs['by'])) {
$this->paginate['Tagged'] = array(
'model' => 'Recipe',
'tagged',
'by' => $this->passedArgs['by']);
$recipes = $this->paginate('Tagged');
} else {
$this->Recipe->recursive = 1;
$recipes = $this->paginate();
}
$this->set('recipes', $recipes);
$this->set('tags', $this->Recipe->Tagged->find('cloud', array('limit' => 10)));
}