Re: Question Regarding Model Grandchildren

2010-06-09 Thread cricket
On Jun 9, 10:36 am, Dima  wrote:
> cricket - thanks for the suggestion.  I've been reading up on MPTT,
> but the first link doesn't have the demo described on the site.  I was
> wondering if you could post our example just so I can go through it
> and see how MPTT structured table calls are made.

First, you need to add parent_id, lft, and rght fields (the latter two
are usually spelled that way to avoid conflicts) to your table. Then
set them up according to how the tree should display. Later, the
TreeBehavior will take care of fetching them in the correct nested
order.

I usually use a root node that has parent_id = null to keep things
simple. All of the find calls will include a condition that parent_id
must not be null, so this item is never included in the results. It's
a "virtual menu item", for want of a better term.

That means that the parent_id column should allow null. The lft & rght
should be INT NOT NULL.

Based on your example, you'd have the following records (untested):

name - parent_id - lft - rght
root - null - 1 - 16
MenuItemA - 1 - 2 - 7
SubItemA - 2 - 3 - 6
SubItemB - 2 - 4 - 5
MenuItemB - 1 - 8 - 15
SubMenuA - 8 - 9 - 14
SubItemC - 9 - 10 - 13
SubItemD - 9 - 11 - 12

So your main menu items have parent_id = 1, which is the never-seen
root node of the tree. MenuItemA's children have parent_id = 2 because
that's what the parent's lft column is.

Note that parent_id is not necessarily the id of the parent item.
These 3 fields have nothing to do with the primary key.

Once you've got the records set up correctly, add TreeBehavior to the
model:

var $actsAs = array(
'Tree' => array(
'parent' => 'parent_id',
'left' => 'lft',
'right' => 'rght'
)
);

Next, add a method to the model to fetch the records as a tree. My
model here is Section and I also want each section's Item names. Leave
the contain part out if you don't need something like that. I'm just
including it to show that it can be done, if necessary. Item here has
nothing to do with your MenuItem names. It's just something involved
with my particular application.

public function threaded()
{
$filters = array(
'conditions' => array('Section.parent_id IS NOT NULL'),
'fields' => array('*'),
'order' => array('Section.lft' => 'ASC'),
'contain' => array(
'Item' => array(
'fields' => array('Item.id'),
'order' => array('Item.name' => 'ASC')
)
)
);

return $this->find('threaded', $filters);
}

Then grab it from within your controller. Because this is a navigation
menu, you'll want to cache the result, of course. I would suggest
getting the menu using requestAction from within an element that is
cached.

public function nav()
{
return $this->Section->threaded();
}


Debug the result to ensure that the tree looks correct. From there,
you can either build your menu list yourself or use Andy's TreeHelper.
Using that, your element might look like this:

requestAction('/sections/nav');
?>

generate(
$section_nodes,
array(
'element' => 'sections/nav_node',
'model' => 'Section'
)
);
?>


Make sure to include the helper in the controller's $helpers array.

The helper creates a nested unordered list for the nodes. It applies a
template (here, nav_node.ctp) to each node on the tree. Within that
helper, several variables are available, as shown in Andy's post:

$data // the row of data passed to the helper
$depth // depth in the current tree 1 = first item
$hasChildren // whether the current row has children or not
$hasVisibleChildren // whether the current row has Visible children or
not. Only relavent for MPTT tree data
$numberOfDirectChildren // only avaliable with recursive data
$numberOfTotalChildren // only available with MPTT tree data
$firstChild // whether the current row is the first of it's siblings
or not
$lastChild // whether the current row is the last of it's siblings or
not

These allow you to apply different classes to the link, if desired,
based on where the node falls on the tree.

So, your nav_node.ctp, at its most basic might look like this:

echo $html->link(
  $data['Section']['name'],
  array('controller' => 'sections', 'action' => 'view', 'id' =>
$data['Section']['id']),
  array('title' => 'click to view this section')
);


But you can use the variables above to apply different classes, etc.
based on the position.

When you add a new Section, include a hidden field for the parent_id.
TreeBehavior will do the rest.

Check out the new CakePHP Questions site http://cakeqs.org and help others with 
their CakePHP related questions.

You received this message because you are subscribed to the Google Groups 
"CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscr

Re: Question Regarding Model Grandchildren

2010-06-09 Thread Dima
cricket - thanks for the suggestion.  I've been reading up on MPTT,
but the first link doesn't have the demo described on the site.  I was
wondering if you could post our example just so I can go through it
and see how MPTT structured table calls are made.

Thanks,
Dima

On Jun 8, 8:10 pm, cricket  wrote:
> On Jun 8, 4:31 pm, Dima  wrote:
>
> > First, sorry if subject name isn't accurate; I don't know how exactly
> > to phrase what I'm searching for...
>
> I know the situation. But yours seems apt.
>
>
>
> > Here's the issue- I have a table which generates a menu for me.  The
> > table has primary_key, name, parent_id, display, order_in_list.  Below
> > is a sample table with display and order_in_list removed.
> > primary  key
> > ...
>
> > Here's roughly what the menu should look like:
>
> > -MenuItemA
> >     -SubItemA
> >     -SubItemB
> > -MenuItemB
> >     -SubMenuA
> >         -SubItemC
> >         -SubItemD
>
> > This is what my model currently is:
>
> > var $hasMany = array
> > (
> >         'ChildNavMenu'=>array
> >         (
> >                 'className'=>'Navmenu',
> >                 'foreignKey'=>'parent_id',
> >                 'conditions'=>array
> >                 (
> >                         'display'=>'1'
> >                 ),
> >                 'order'=>'order_in_list'
> >         )
> > );
>
> > This correctly creates children of parents, BUT fails to create
> > children of children of parents (SubItemC + SubItemD in example
> > above.)  Does anybody know of a way to change the $hasMany in order to
> > include this critical data?
>
> > Thanks,
> > Dima
>
> You'd have to create a model for the child menu items, then create a
> hasMany assoc. with grandchild items.
> If it were up to me, I'd use MPTT [1] and TreeBehavior. That way, you
> don't need to create child (or grandchild) models. This is especially
> important if the branch may go deeper. You simply have one model for
> all menu items and specify the parent_id, left, and right (see
> explanation at the links below). The TreeBehavior makes using this
> quite simple.
>
> [1] Modified Preorder Tree 
> Traversalhttp://www.ad7six.com/entries/view/56/Working-with-Tree-data-%28MPTT%29http://articles.sitepoint.com/article/hierarchical-data-databasehttp://dev.mysql.com/tech-resources/articles/hierarchical-data.html
>
> There's also AD76's TreeHelper. Highly 
> recommended.http://bakery.cakephp.org/articles/view/tree-helper-1
>
> It can be a bit confusing to set up the templates for the helper but
> it works like gangbusters. Have a look at all this and let me know if
> you need some help. I can give you a complete example using a Section
> model (basically, a file system hierarchy) that works really well.

Check out the new CakePHP Questions site http://cakeqs.org and help others with 
their CakePHP related questions.

You received this message because you are subscribed to the Google Groups 
"CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to
cake-php+unsubscr...@googlegroups.com For more options, visit this group at 
http://groups.google.com/group/cake-php?hl=en


Re: Question Regarding Model Grandchildren

2010-06-08 Thread cricket
On Jun 8, 4:31 pm, Dima  wrote:
> First, sorry if subject name isn't accurate; I don't know how exactly
> to phrase what I'm searching for...

I know the situation. But yours seems apt.

> Here's the issue- I have a table which generates a menu for me.  The
> table has primary_key, name, parent_id, display, order_in_list.  Below
> is a sample table with display and order_in_list removed.
> primary  key
> ...
>
> Here's roughly what the menu should look like:
>
> -MenuItemA
>     -SubItemA
>     -SubItemB
> -MenuItemB
>     -SubMenuA
>         -SubItemC
>         -SubItemD
>
> This is what my model currently is:
>
> var $hasMany = array
> (
>         'ChildNavMenu'=>array
>         (
>                 'className'=>'Navmenu',
>                 'foreignKey'=>'parent_id',
>                 'conditions'=>array
>                 (
>                         'display'=>'1'
>                 ),
>                 'order'=>'order_in_list'
>         )
> );
>
> This correctly creates children of parents, BUT fails to create
> children of children of parents (SubItemC + SubItemD in example
> above.)  Does anybody know of a way to change the $hasMany in order to
> include this critical data?
>
> Thanks,
> Dima

You'd have to create a model for the child menu items, then create a
hasMany assoc. with grandchild items.
If it were up to me, I'd use MPTT [1] and TreeBehavior. That way, you
don't need to create child (or grandchild) models. This is especially
important if the branch may go deeper. You simply have one model for
all menu items and specify the parent_id, left, and right (see
explanation at the links below). The TreeBehavior makes using this
quite simple.

[1] Modified Preorder Tree Traversal
http://www.ad7six.com/entries/view/56/Working-with-Tree-data-%28MPTT%29
http://articles.sitepoint.com/article/hierarchical-data-database
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html

There's also AD76's TreeHelper. Highly recommended.
http://bakery.cakephp.org/articles/view/tree-helper-1

It can be a bit confusing to set up the templates for the helper but
it works like gangbusters. Have a look at all this and let me know if
you need some help. I can give you a complete example using a Section
model (basically, a file system hierarchy) that works really well.


Check out the new CakePHP Questions site http://cakeqs.org and help others with 
their CakePHP related questions.

You received this message because you are subscribed to the Google Groups 
"CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to
cake-php+unsubscr...@googlegroups.com For more options, visit this group at 
http://groups.google.com/group/cake-php?hl=en


Question Regarding Model Grandchildren

2010-06-08 Thread Dima
First, sorry if subject name isn't accurate; I don't know how exactly
to phrase what I'm searching for...

Here's the issue- I have a table which generates a menu for me.  The
table has primary_key, name, parent_id, display, order_in_list.  Below
is a sample table with display and order_in_list removed.
primary  key
|name
||parent_id
|| |
|| |
1   MenuItemA   0
2   MenuItemB   0
3   SubItemA  1
4   SubItemB  1
5   SubMenuA2
6   SubItemC 5
7   SubItemD 5

Here's roughly what the menu should look like:

-MenuItemA
-SubItemA
-SubItemB
-MenuItemB
-SubMenuA
-SubItemC
-SubItemD

This is what my model currently is:

var $hasMany = array
(
'ChildNavMenu'=>array
(
'className'=>'Navmenu',
'foreignKey'=>'parent_id',
'conditions'=>array
(
'display'=>'1'
),
'order'=>'order_in_list'
)
);

This correctly creates children of parents, BUT fails to create
children of children of parents (SubItemC + SubItemD in example
above.)  Does anybody know of a way to change the $hasMany in order to
include this critical data?

Thanks,
Dima

Check out the new CakePHP Questions site http://cakeqs.org and help others with 
their CakePHP related questions.

You received this message because you are subscribed to the Google Groups 
"CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to
cake-php+unsubscr...@googlegroups.com For more options, visit this group at 
http://groups.google.com/group/cake-php?hl=en