# Tree - Nestedset behavior extension for Doctrine 2
**Tree** nested behavior will implement the standard Nested-Set behavior
on your Entity. Tree supports different strategies and currently the alternative
to **nested-set** can be **closure-table** tree. Also this behavior can be nested
with other extensions to translate or generated slugs of your tree nodes.
Features:
- Closure tree strategy, may be faster in some cases where ordering does not matter
- Support for multiple roots in nested-set
- No need for other managers, implementation is through event listener
- Synchronization of left, right values is automatic
- Can support concurrent flush with many objects being persisted and updated
- Can be nested with other extensions
- Annotation, Yaml and Xml mapping support for extensions
[blog_reference]: http://gediminasm.org/article/tree-nestedset-behavior-extension-for-doctrine-2 "Tree - Nestedset or Closure extension for Doctrine 2 makes tree implementation on entities"
[blog_test]: http://gediminasm.org/test "Test extensions on this blog"
Thanks for contributions to:
- **[comfortablynumb](http://github.com/comfortablynumb) Gustavo Adrian** for Closure strategy
- **[everzet](http://github.com/everzet) Kudryashov Konstantin** for TreeLevel implementation
- **[stof](http://github.com/stof) Christophe Coevoet** for getTreeLeafs function
Update **2011-05-07**
- Tree is now able to act as **closure** tree, this strategy was refactored
and now fully functional. It is much faster for file-folder trees for instance
where you do not care about tree ordering.
Update **2011-04-11**
- Made in memory node synchronization, this change does not require clearing the cached nodes after any updates
to nodes, except **recover, verify and removeFromTree** operations.
Update **2011-02-08**
- Refactored to support multiple roots
- Changed the repository name, relevant to strategy used
- New [annotations](#annotations) were added
Update **2011-02-02**
- Refactored the Tree to the ability on supporting diferent tree models
- Changed the repository location in order to support future updates
**Note:**
- You can [test live][blog_test] on this blog
- After using a NestedTreeRepository functions: **verify, recover, removeFromTree** it is recommended to clear EntityManager cache
because nodes may have changed values in database but not in memory. Flushing dirty nodes can lead to unexpected behaviour.
- Closure tree implementation is experimental and not fully functional, so far not documented either
- Public [Tree repository](http://github.com/l3pp4rd/DoctrineExtensions "Tree extension on Github") is available on github
- Last update date: **2012-01-02**
**Portability:**
- **Tree** is now available as [Bundle](http://github.com/stof/StofDoctrineExtensionsBundle)
ported to **Symfony2** by **Christophe Coevoet**, together with all other extensions
This article will cover the basic installation and functionality of **Tree** behavior
Content:
- [Including](#including-extension) the extension
- [Attaching](#event-listener) the **Tree Listener**
- Entity [example](#entity)
- [Yaml](#yaml) mapping example
- [Xml](#xml) mapping example
- Basic usage [examples](#basic-examples)
- Build [html tree](#html-tree)
- Advanced usage [examples](#advanced-examples)
## Setup and autoloading {#including-extension}
If you using the source from github repository, initial directory structure for
the extension library should look like this:
```
...
/DoctrineExtensions
/lib
/Gedmo
/Exception
/Loggable
/Mapping
/Sluggable
/Timestampable
/Translatable
/Tree
/tests
...
...
```
First of all we need to setup the autoloading of extensions:
``` php
register();
```
### Attaching the Tree Listener to the event manager {#event-listener}
To attach the **Tree Listener** to your event system:
``` php
addEventSubscriber($treeListener);
// now this event manager should be passed to entity manager constructor
```
## Tree Entity example: {#entity}
**Note:** that Node interface is not necessary, except in cases there
you need to identify entity as being Tree Node. The metadata is loaded only once then
cache is activated
``` php
id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function setParent(Category $parent = null)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
}
```
### Tree annotations: {#annotations}
- **@Gedmo\Mapping\Annotation\Tree(type="strategy")** this **class annotation** is used to set the tree strategy by **type** parameter.
Currently **nested** or **closure** strategy is supported
- **@Gedmo\Mapping\Annotation\TreeLeft** it will use this field to store tree **left** value
- **@Gedmo\Mapping\Annotation\TreeRight** it will use this field to store tree **right** value
- **@Gedmo\Mapping\Annotation\TreeParent** this will identify this column as the relation to **parent node**
- **@Gedmo\Mapping\Annotation\TreeLevel** it will use this field to store tree**level**
- **@Gedmo\Mapping\Annotation\TreeRoot** it will use this field to store tree**root** id value
## Yaml mapping example {#yaml}
Yaml mapped Category: **/mapping/yaml/Entity.Category.dcm.yml**
```
---
Entity\Category:
type: entity
repositoryClass: Gedmo\Tree\Entity\Repository\NestedTreeRepository
table: categories
gedmo:
tree:
type: nested
id:
id:
type: integer
generator:
strategy: AUTO
fields:
title:
type: string
length: 64
lft:
type: integer
gedmo:
- treeLeft
rgt:
type: integer
gedmo:
- treeRight
root:
type: integer
nullable: true
gedmo:
- treeRoot
lvl:
type: integer
gedmo:
- treeLevel
manyToOne:
parent:
targetEntity: Entity\Category
inversedBy: children
joinColumn:
name: parent_id
referencedColumnName: id
onDelete: SET NULL
gedmo:
- treeParent
oneToMany:
children:
targetEntity: Entity\Category
mappedBy: parent
```
## Xml mapping example {#xml}
``` xml