Development

/plugins/sfPropelActAsNestedSetBehaviorPlugin/README

You must first sign up to be able to contribute.

root/plugins/sfPropelActAsNestedSetBehaviorPlugin/README

Revision 3470, 6.9 kB (checked in by tristan, 6 years ago)

releasing 0.6.1

Line 
1 = sfPropelActAsNestedSetBehaviorPlugin plugin =
2
3 [[PageOutline]]
4
5 The `sfPropelActAsNestedSetBehaviorPlugin` is a symfony plugin that provides nested set capabilities to Propel objects.
6
7 Nested sets (aka modified preorder tree traversal) is a very efficient way (in terms of performances) to browse and edit a tree like structure in an RDBMS.
8
9 You can read [http://dev.mysql.com/tech-resources/articles/hierarchical-data.html a good introduction to nested sets] on MySQL developers' zone.
10
11 == Features ==
12
13  * Fully unit tested
14  * Possibility to store multiple trees in the same table
15  * Atomic operations
16  * Also maintains adjacency list properties, making your classes compatible with code based on this tree traversal methodology
17
18 == Installation ==
19
20   * Install the plugin
21  
22     {{{
23       symfony plugin-install http://plugins.symfony-project.com/sfPropelActAsNestedSetBehaviorPlugin
24     }}}
25
26   * Enable Propel behavior support in `propel.ini`:
27
28     {{{
29       propel.builder.AddBehaviors = true
30     }}}
31  
32     If you have to enable the behavior support, rebuild your model:
33
34     {{{
35       symfony propel-build-model
36     }}}
37
38   * Enable the behavior for one of your Propel model:
39
40     {{{
41       // lib/model/ForumPost.php
42       class ForumPost
43       {
44       }
45
46       $columns_map = array('left'   => ForumPostPeer::TREE_LEFT,
47                            'right'  => ForumPostPeer::TREE_RIGHT,
48                            'parent' => ForumPostPeer::TREE_PARENT,
49                            'scope'  => ForumPostPeer::TOPIC_ID);
50  
51       sfPropelBehavior::add('ForumPost', array('actasnestedset' => array('columns' => $columns_map)));
52     }}}
53
54   The ''column map'' is used by the behavior to know which columns hold information it needs :
55  
56     * left : Model column holding nested set left value for a row
57     * right : Model column holding nested set right value for a row
58     * parent : Model column holding row's parent id (this is necessary because we use adjacency list tree traversal for some methods)
59     * scope : Model column holding row's scope id. The scope is used to differenciate trees stored in the same table
60
61 == Usage ==
62
63 === Simple tree creation ===
64
65 {{{
66 #!php
67   $root = new ForumPost();
68   $root->makeRoot();
69   $root->save();
70
71   $p1 = new ForumPost();
72   $p1->insertAsFirstChildOf($root);
73   $p1->save();
74
75   $p2 = new ForumPost();
76   $p2->insertAsFirstChildOf($p1);
77   $p2->save();
78
79   /*
80    * Resulting tree :
81    *
82    * ROOT
83    * |- P1
84    *    |- P2
85    */
86 }}}
87
88 === Multiple trees in a single table ===
89
90 {{{
91 #!php
92   $root1 = new ForumPost();
93   $root1->makeRoot();
94   $root1->setTopicId(1);
95   $root1->save();
96
97   $root2 = new ForumPost();
98   $root2->makeRoot();
99   $root2->setTopicId(2);
100   $root2->save();
101
102   $p1 = new ForumPost();
103   $p1->insertAsFirstChildOf($root1);
104   $p1->save();
105
106   $p2 = new ForumPost();
107   $p2->insertAsFirstChildOf($root2);
108   $p2->save();
109
110   /*
111    * Resulting trees :
112    *
113    * ROOT1
114    * |- P1
115    *
116    * ROOT2
117    * |- P2
118    */
119 }}}
120
121 === Lame threaded forum posts list example ===
122
123 {{{
124   $root = ForumPostPeer::retrieveByPk(rootnodepk);
125   <ul>
126     <?php echo $root->getTitle() ?>
127
128     <?php foreach ($root->getDescendants() as $post): ?>
129
130        <li style="padding-left: <?php echo $post->getLevel() ?>em;">
131             <?php echo $post->getTitle() ?>
132        </li>
133
134     <?php endforeach; ?>
135   </ul>
136 }}}
137
138 === Using nested sets and sfPropelPager ===
139
140 {{{
141   // Decide which posts to fetch
142   $c = new Criteria();
143   $c->add(ForumPostPeer::TOPIC_ID, $topic_id);
144   $c->addAscendingOrderByColumn(ForumPostPeer::TREE_LEFT); // ForumPostPeer::TREE_LEFT is the column holding nested set's left value
145    
146   // Create pager
147   $pager = new sfPropelPager('ForumPost', 10);
148   $pager->setCriteria($c);
149   $pager->setPage($this->getRequestParameter('page', 1));
150   $pager->init();
151 }}}
152
153 == Public API ==
154
155 Enabling the behaviors adds the following method to the Propel objects :
156
157 === Insertion methods ===
158
159  * {{{void insertAsFirstChildOf(BaseObject $dest_node)}}} : Inserts node as first child of given node.
160  * {{{void insertAsLastChildOf(BaseObject $dest_node)}}} : Inserts node as last child of given node.
161  * {{{void insertAsNextSiblingOf(BaseObject $dest_node)}}} : Inserts node as next sibling of given node.
162  * {{{void insertAsPrevSiblingOf(BaseObject $dest_node)}}} : Inserts node as previous sibling of given node.
163
164 === Informational methods ===
165
166  * {{{bool hasChildren()}}} : Returns true if given node as one or several children.
167  * {{{bool isRoot()}}} : Returns true if given node is a root node.
168  * {{{bool hasParent()}}} : Returns true if given node has a parent node.
169  * {{{bool hasNextSibling()}}} : Returns true if given node has a next sibling.
170  * {{{bool hasPrevSibling()}}} : Returns true if given node has a previous sibling.
171  * {{{bool isLeaf()}}} : Returns true if given node does not have children.
172  * {{{integer getNumberOfChildren()}}} : Returns given node number of direct children.
173  * {{{integer getNumberOfDescendants()}}} : Returns given node number of descendants (n level).
174  * {{{integer getLevel()}}} : Returns given node level.
175
176 === Node retrieval methods ===
177
178  * {{{array getChildren($peer_method = 'doSelect')}}} : Returns given node direct children.
179  * {{{array getDescendants($peer_method = 'doSelect')}}} : Returns given node descendants (n level).
180  * {{{BaseObject retrieveNextSibling()}}} : Returns given node next sibling.
181  * {{{BaseObject retrievePrevSibling()}}} : Returns given node previous sibling.
182  * {{{BaseObject retrieveFirstChild()}}} : Returns given node first child.
183  * {{{BaseObject retrieveLastChild()}}} : Returns given node last child.
184  * {{{BaseObject retrieveParent()}}} : Returns given node parent.
185  * {{{array getPath()}}} : Returns path to a specific node as an array, useful to create breadcrumbs.
186
187 === Tree modification methods ===
188
189  * {{{void moveToFirstChildOf(BaseObject $dest_node)}}} : Moves node to first child of given node.
190  * {{{void moveToLastChildOf(BaseObject $dest_node)}}} : Moves node to last child of given node.
191  * {{{void moveToNextSiblingOf()}}} : '''NOT IMPLEMENTED YET'''
192  * {{{void moveToPrevSiblingOf()}}} : '''NOT IMPLEMENTED YET'''
193  * {{{void deleteChildren()}}} : '''NOT IMPLEMENTED YET'''
194  * {{{void deleteTree()}}} : '''NOT IMPLEMENTED YET'''
195
196 === Helper methods ===
197
198  * {{{void makeRoot()}}} : Sets node properties to make it a root node.
199  * {{{BaseObject reload()}}} : Returns an up to date version of node
200
201 == Changelog ==
202
203 === 2007-02-15 | 0.6.1 ===
204
205 Fixed minor bug in getPath()
206
207 === 2007-02-15 | 0.6.0 ===
208
209 Implemented missing node retrieval methods :
210
211  * retrieveFirstChild
212  * retrieveLastChild
213  * retrieveParent
214  * getPath
215  
216 Updated docs and unit tests accordingly
217
218 === 2007-02-14 | 0.5.1 ===
219
220 Pear package missed plugin's config.php file.
221
222 === 2007-02-14 | 0.5.0 ===
223
224 Initial public release. The behavior is stable and fully unit-tested, but the API is not yet complete. Missing methods :
225
226  * retrieveFirstChild
227  * retrieveLastChild   
228  * moveToPrevSiblingOf
229  * moveToNextSiblingOf
230  * deleteChildren
231  * deleteTree
232  * getPath
Note: See TracBrowser for help on using the browser.