New feature: bindModel/unbindModel

This feature allows you to bind or turn off associations on the fly, and will be available in the next release (RC6?) of CakePHP.

Let us start with an unbindModel example. We have three models: User, Project and Supportrequest. A user has many projects and many support requests. If we do

debug($this->User->findAll());

the output would be something like:

Array
(
    [0] => Array
        (
            [User] => Array
                (
                    [id] => 1
                    [firstname] => Daniel
                    [lastname] => Hofstetter
                )
           [Project] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [user_id] => 1
                            [name] => project A
                        )
                )
            [Supportrequest] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [user_id] => 1
                            [comment] => a support request
                        )
                    [1] => Array
                        (
                            [id] => 2
                            [user_id] => 1
                            [comment] => another support request
                        )
                )
        )
)

Ok, but what if we are only interested in the users and the projects? Well, we could simply ignore the support requests. Or we could turn off the association to the support requests with unbindModel:

$this->User->unbindModel(array('hasMany' => array('Supportrequest')));
debug($this->User->findAll());

That gives us the following output:

Array
(
    [0] => Array
        (
            [User] => Array
                (
                    [id] => 1
                    [firstname] => Daniel
                    [lastname] => Hofstetter
                )
           [Project] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [user_id] => 1
                            [name] => project A
                        )
                )
)

Notice: The associations are reset after each call to a find function.

Ok, that was the unbindModel example. Let us go to the bindModel example. That example will be a little bit artificial as I do not see a real use case for bindModel at the moment. Maybe you know one? Ok, we have two Models: User and Supportrequest. The model do not have any associations. If we do

debug($this->User->findAll());

we get the following output:

Array
(
    [0] => Array
        (
            [User] => Array
                (
                    [id] => 1
                    [firstname] => Daniel
                    [lastname] => Hofstetter
                )
        )
)

For some reason we want to have a temporary “hasMany” association between user and support request. We define it in the following way using the usual association syntax:

$this->User->bindModel(array('hasMany' => array('Supportrequest' => 
                             array('foreignKey' => 'user_id'))));
debug($this->User->findAll());

And that is the output:

Array
(
    [0] => Array
        (
            [User] => Array
                (
                    [id] => 1
                    [firstname] => Daniel
                    [lastname] => Hofstetter
                )
            [Supportrequest] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [user_id] => 1
                            [comment] => a support request
                        )
                    [1] => Array
                        (
                            [id] => 2
                            [user_id] => 1
                            [comment] => another support request
                        )
                )
        )
)

That’s it :)

13 Comments

  1. odpocinek
    Posted February 23, 2006 at 12:50 am | Permalink

    $this->User->hasMany = array();
    $this->User->__createLinks();

    in controller, or

    $this->hasMany = array();
    $this->__createLinks();

    in model User does a similar (not very clean) trick.

  2. Posted February 23, 2006 at 1:38 am | Permalink

    odpocinek,

    Your using private methods that should not be used.

    $this->__createLinks();

  3. Posted April 7, 2006 at 9:42 am | Permalink

    I suppose the idea behind bindModel is so that you don’t have to link a very large and rarely used association.

    For one, I’ve got a customer linked to transactions. There are _loads_ of transactions, so I will only bind it if and when I need it, which is in far fewer places than I need to use customer.

  4. Posted June 24, 2006 at 12:48 am | Permalink

    I can give you an example of why I needed to use the bindModel method…
    I have a list of users and the users have many images but one image is their main profile image so when I display their profile I want all the images but when I display their name in the forums I just want where img_main = 1

    so that I don’t get an array of 30 images when I just need the one.

    great framework by the way, I’m loving it so far

  5. Posted June 24, 2006 at 8:58 am | Permalink

    @Jim Plush: thanks for the example :)

  6. fraisouille
    Posted August 17, 2006 at 8:55 pm | Permalink

    Could it work for “submodels” ?

    I explain my problem: I’m working in my “news” controller. I’m retrieving the data for a particular news.

    A news has many newsRead. A newsRead is the association between a news and a user, so a newsRead belongs to news and to user.

    But when I retrieve my news newsRead list, I don’t want to have the whole news data again with my recursive mode. So I would like to unbind temporary the associaction between newsRead and user.

    But when I do my unbind in my news controller (I’m not in my newsRead controller !) it does not have effect for my $this->News->findAllById($id)
    (I’ve tried with $this->NewsRead->findAll and there it works.)

    Am I trying to do something impossible ? Or is there an unknown trick ?

  7. purepear
    Posted August 18, 2006 at 12:44 pm | Permalink

    OK… my problem is similar to this.

    The example:
    Category->Subcategory->Product They all have hasMany and belongsTo as usual.

    I want to get all Products that belongs to a certain Category … and i want the results to to be sth. like this:

    Array{
    [Product] => array{

    }

    [Subcategory] => array{

    [Category] => array{

    }
    }

    }

    or :

    Array{
    [Product] => array{

    [Subcategory] => array{

    [Category] => array{

    }
    }
    }
    }

    How do i do this ?
    I tried the Product->recursive = 2 and it went to a deep recursion doubling all my Subcategoris and Products inside each other… big mess.
    I played around with unbindModel() too but i didn’t get the result i wanted.

    Just a simple example should be enough.
    Thanks in advance.

  8. purepear
    Posted August 18, 2006 at 1:11 pm | Permalink

    OK solved :

    $this->Category->unbindModel(array(‘hasMany’ => array(‘Subcategory’)));
    $this->Category->Subcategory->unbindModel(array(‘hasMany’ => array(‘Product’)));

    $conditions = array(‘Subcategory.category_id’ => $id);
    $data = $this->Product->findAll($conditions, NULL, $order, $limit, $page);

    I wonder what i got wrong before :)
    anyway .. it works

  9. fraisouille
    Posted August 18, 2006 at 5:51 pm | Permalink

    That was the solution !
    I didn’t thought we could call $this->Category->Subcategory…

    Thanks !

  10. Posted August 19, 2006 at 1:07 pm | Permalink

    @purepear, fraisouille: I am glad you could solve your issues :)

  11. Posted August 29, 2007 at 7:52 pm | Permalink

    Thanks cakebaker!

    Because of this article, I just got past a big holdup on a project I had been working on.

  12. Posted August 30, 2007 at 8:33 am | Permalink

    @doubleswizz: Cool to hear that :)

    Btw: This blog moved to http://cakebaker.42dh.com

  13. Posted March 2, 2011 at 12:32 pm | Permalink

    Nice tutorial….thanks for this post…..
    Please visit this link for learn more script.
    http://amitmondal.wordpress.com/


One Trackback/Pingback

  1. […] New feature: bindModel/unbindModel « cakebaker A couple Cake tricks in Posts@ rd11, supporters of CakePHP and developers of innovative web […]

Post a Comment

Required fields are marked *
*
*

%d bloggers like this: