Wednesday, October 27, 2010

Re: Question about DB relationships

On Wed, Oct 27, 2010 at 7:18 PM, dingerkingh <dingerkingh@hotmail.com> wrote:
> I will try to keep this as simple as possible.  I have read through
> the manual but can't seem to find what I am looking - however, I am
> sure it is in there somewhere.
>
> Here is what I am I am looking to do on a very small scale:
>
> names
> id
> name
>
> tickets
> id
> title
> name_id
> closed_by
>
> What I need to have is closed_by be the same thing as name_id.
>
> When I use name_id and cake bake it automagically creates the drop
> downs for the add and edit page because it is linked to the names
> table.  How would I make closed_by do the same thing? I hope this
> makes sense...
>
> name_id and closed_id I would like both to be generated from the names
> table. Thanks in advance!

What you're after is a self-join relationship. To do that, you use a
model alias but the same classname. That's why, in the association
arrays, you'll see something like:

'SomeModelName' => array(
'className' => 'SomeModelName',
etc.

The reason for the repetition is that the outer array key is the
model's alias. Often, the alias and class name are one and the same,
so it seems pointless at first, but it's very, /very/ cool.

So, to do a self-join on Foo model, where each Foo might have a parent
and children:

public $belongsTo = array(
'ParentFoo' => array(
'className' => 'Foo',
'foreignKey' => 'parent_id'
),
);

public $hasMany = array(
'ChildFoo' => array(
'className' => 'Foo',
'foreignKey' => 'parent_id'
),
);

So, for ParentFoo, we're checking Foo.parent_id, while the association
between the latter is Foo.id == ChildFoo.parent_id.

For your situation, I recommend that you use a different model name.
Names are attributes, not things, which is why you've also got a
column called 'name'. Name.name just seems a bit off, and suggests
that the model/class hasn't really been thought through. Better: User,
Member, Person, Flunky ...

So:

class Member extends AppModel
{
public $hasMany = array(
'Ticket' => array(
'className' => 'Ticket',
'foreignKey' => 'member_id'
)
);


class Ticket extends AppModel
{
public $belongsTo = array(
'Opener' => array(
'className' => 'Member'
'foreignKey' => 'opener_id'
),
'Closer' => array(
'className' => 'Member',
'foreignKey' => 'closer_id'
)
);


Now, in your TicketsController, you can do stuff like:

public $paginate = array(
'limit' => 30,
'order' => array('Ticket.created' => ASC'),
'contain' => array(
'Opener',
'Closer'
)
);

You'll then have 'Opener' and 'Closer' (if the Ticket has been closed)
sub-arrays in your paginated data which contain Member info.

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+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php?hl=en

No comments: