Przeglądaj źródła

[Tree] Materialized Path: Added some documentation

comfortablynumb 13 lat temu
rodzic
commit
8e5aac5986
1 zmienionych plików z 260 dodań i 3 usunięć
  1. 260 3
      doc/tree.md

+ 260 - 3
doc/tree.md

@@ -1,12 +1,13 @@
 # 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 
+on your Entity. Tree supports different strategies. Currently it supports
+**nested-set**, **closure-table** and **materialized-path**. Also this behavior can be nested
 with other extensions to translate or generated slugs of your tree nodes.
 
 Features:
 
+- Materialized Path strategy for ORM and ODM (MongoDB)
 - 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
@@ -24,6 +25,9 @@ Thanks for contributions to:
 - **[everzet](http://github.com/everzet) Kudryashov Konstantin** for TreeLevel implementation
 - **[stof](http://github.com/stof) Christophe Coevoet** for getTreeLeafs function
 
+Update **2012-02-23**
+- Added a new strategy to support the "Materialized Path" tree model. It works on ODM (MongoDB) and ORM.
+
 Update **2011-05-07**
 
 - Tree is now able to act as **closure** tree, this strategy was refactored
@@ -73,6 +77,7 @@ Content:
 - Basic usage [examples](#basic-examples)
 - Build [html tree](#html-tree)
 - Advanced usage [examples](#advanced-examples)
+- [Materialized Path](#materialized-path)
 
 <a name="including-extension"></a>
 
@@ -186,12 +191,21 @@ class Category
 ### Tree 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
+Currently **nested**, **closure** or **materializedPath** strategies are supported. An additional "activateLocking" parameter
+is available if you use the "Materialized Path" strategy with MongoDB. It's used to activate the locking mechanism (more on that
+in the corresponding section).
 - **@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
+- **@Gedmo\Mapping\Annotation\TreePath** (Materialized Path only) it will use this field to store the "path". It has an
+optional parameter "separator" to define the separator used in the path
+- **@Gedmo\Mapping\Annotation\TreePathSource** (Materialized Path only) it will use this field as the source to
+ construct the "path"
+- **@Gedmo\Mapping\Annotation\TreeLockTime** (Materialized Path - ODM MongoDB only) this field is used if you need to
+use the locking mechanism with MongoDB. It persists the lock time if a root node is locked (more on that in the corresponding
+section).
 
 <a name="yaml-mapping"></a>
 
@@ -744,3 +758,246 @@ translated. Because the postLoad event never will be triggered
 Now the generated treenode slug will be translated by Translatable behavior
 
 Easy like that, any suggestions on improvements are very welcome
+
+<a name="materialized-path"></a>
+
+## Materialized Path
+
+### Important notes before defining the schema
+
+- If you use MongoDB you should activate the locking mechanism provided to avoid inconsistencies in cases where concurrent
+modifications on the tree could occur. Look at the MongoDB example of schema definition to see how it must be configured.
+- If your "TreePathSource" field is of type "string", then the primary key will be concatenated in the form: "value-id".
+ This is to allow you to use non-unique values as the path source. For example, this could be very useful if you need to
+ use the date as the path source (maybe to create a tree of comments and order them by date).
+- "TreePath" field can only be of types: string, text
+- "TreePathSource" field can only be of types: id, integer, smallint, bigint, string, int, float (I include here all the
+variations of the field types, including the ORM and ODM for MongoDB ones).
+- "TreeLockTime" must be of type "date" (used only in MongoDB for now).
+
+### ORM Entity example (Annotations)
+
+``` php
+<?php
+
+namespace Entity;
+
+use Gedmo\Mapping\Annotation as Gedmo;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\MaterializedPathRepository")
+ * @Gedmo\Tree(type="materializedPath")
+ */
+class Category
+{
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue
+     */
+    private $id;
+
+    /**
+     * @Gedmo\TreePath
+     * @ORM\Column(name="path", type="string", length=3000, nullable=true)
+     */
+    private $path;
+
+    /**
+     * @Gedmo\TreePathSource
+     * @ORM\Column(name="title", type="string", length=64)
+     */
+    private $title;
+
+    /**
+     * @Gedmo\TreeParent
+     * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
+     * @ORM\JoinColumns({
+     *   @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
+     * })
+     */
+    private $parent;
+
+    /**
+     * @Gedmo\TreeLevel
+     * @ORM\Column(name="lvl", type="integer", nullable=true)
+     */
+    private $level;
+
+    /**
+     * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
+     */
+    private $children;
+
+    public function getId()
+    {
+        return $this->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;
+    }
+
+    public function setPath($path)
+    {
+        $this->path = $path;
+    }
+
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    public function getLevel()
+    {
+        return $this->level;
+    }
+}
+
+```
+
+### MongoDB example (Annotations)
+
+``` php
+<?php
+
+namespace Document;
+
+use Gedmo\Mapping\Annotation as Gedmo;
+use Doctrine\ODM\MongoDB\Mapping\Annotations as MONGO;
+
+/**
+ * @MONGO\Document(repositoryClass="Gedmo\Tree\Document\MongoDB\Repository\MaterializedPathRepository")
+ * @Gedmo\Tree(type="materializedPath", activateLocking=true)
+ */
+class Category
+{
+    /**
+     * @MONGO\Id
+     */
+    private $id;
+
+    /**
+     * @MONGO\Field(type="string")
+     * @Gedmo\TreePathSource
+     */
+    private $title;
+
+    /**
+     * @MONGO\Field(type="string")
+     * @Gedmo\TreePath(separator="|")
+     */
+    private $path;
+
+    /**
+     * @Gedmo\TreeParent
+     * @MONGO\ReferenceOne(targetDocument="Category")
+     */
+    private $parent;
+
+    /**
+     * @Gedmo\TreeLevel
+     * @MONGO\Field(type="int")
+     */
+    private $level;
+
+    /**
+     * @Gedmo\TreeLockTime
+     * @MONGO\Field(type="date")
+     */
+    private $lockTime;
+
+    public function getId()
+    {
+        return $this->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;
+    }
+
+    public function getLevel()
+    {
+        return $this->level;
+    }
+
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    public function getLockTime()
+    {
+        return $this->lockTime;
+    }
+}
+
+```
+
+### Path generation
+
+When an entity is inserted, a path is generated using the value of the field configured as the TreePathSource.
+If For example:
+
+``` php
+$food = new Category();
+$food->setTitle('Food');
+
+$em->persist($food);
+$em->flush();
+
+// This would print "Food-1" assuming the id is 1.
+echo $food->getPath();
+
+$fruits = new Category();
+$fruits->setTitle('Fruits');
+$fruits->setParent($food);
+
+$em->persist($fruits);
+$em->flush();
+
+// This would print "Food-1,Fruits-2" assuming that $food id is 1, $fruits id is 2 and separator = "|" (the default value)
+echo $fruits->getPath();
+
+```
+
+### Locking mechanism for MongoDB
+
+Why you need a locking mechanism for MongoDB? Sadly, MongoDB lacks of full transactional support, so if two or more
+users try to modify the same tree concurrently, it could lead to an inconsistent tree. So we've implemented a simple
+locking mechanism to avoid this type of problems. It works like this: As soon as a user tries to modify a node of a tree,
+it first check if the root node is locked (or if the current lock has expired). If it is locked, then it throws an
+exception of type "Gedmo\Exception\TreeLockingException". If it's not locked, it locks the tree and proceed with the
+modification.