-
Notifications
You must be signed in to change notification settings - Fork 5
model binding
You can bind two models together so that the results from a fetchAll() or fetchRow() call contain not only the subject model but also records related to the record(s). Whatever relationship you spawn, you can bind.
The simplest bindModel call looks like this:
<?php
$modelBlogPost->bindModel('Model_Tag');
?>
This simply says fetch related tags along with the next BlogPost fetch call.
Keep in mind that bindings are made at class level. This allows you to do recursive bindings:
<?php
$modelUser->bindModel('Model_Profile');
$modelComment->bindModel('Model_User');
$modelBlogPost->bindModel('Model_Comment');
?>
A $modelBlogPost->fetchAll() call will now fetch all posts, with all related comments, with all related users, with all related profiles. As long as there's a binding in place, a related recordset will be fetched.
<?php
$modelUser->bindModel('Profile');
?>
This will look for the rule Profile in the referenceMap of Model_User, and use that information to setup the binding.
<?php
$modelUser->bindModel('Model_Comment');
?>
comment is probably not in the referenceMap of Model_User, since comment contains the foreign key (user_id). In that case you must use the full modelname, so that Garp knows what to look for. If you have multiple relationships between models you have to specify the rule. For instance every model in Garp has an Author and a Modifier, both of which are represented thru Model_User. So if you would just use
<?php
$modelBlogPost->bindModel('Model_User');
?>
you would get the first relationship to Model_User that is defined in the referenceMap (usually this is Author). In such cases you can provide a rule to clear up ambiguity:
<?php
$modelBlogPost->bindModel('Model_User', array('rule' => 'Modifier'));
?>
In the case of HABTM you can provide which bindingModel to use:
<?php
$modelBlogPost->bindModel('Model_Tag', array(
'bindingModel' => 'Model_BlogPostTag'
));
?>
Mind you, if no belongsTo or hasOne relationship has been found Garp will try to resolve the bindingModel itself as it assumes hasAndBelongsToMany in the absence of the other types.
In fact, you can go so far as to provide both rules if you really have that much ambiguity to clear:
<?php
$modelBlogPost->bindModel('Model_Tag', array(
'bindingModel' => 'Model_BlogPostTag',
// Note: both these rules are in the referenceMap of
// Model_BlogPostTag
'rule' => 'BlogPost',
'rule2' => 'Tag'
));
?>
Binding a model under a different name Another helpful option is modelClass. Use this if you wish to retrieve records under a different alias:
<?php
$modelBlogPost->bindModel('Human', array(
'modelClass' => 'Model_User'
));
?>
The related Model_User records will now be in $record->Human.
Last but not least, to resolve an absolute edge-case, there's the mode parameter. It's used to clear ambiguity in the case of homophilic relationships. If you do not have multiple homophilic relationships to a single model, you do not need this. In a homophilic parent - child relationship, for instance, there are effectively two relationships to itself, a belongsTo and a hasMany. Take a hierarchical navigation for example, a MenuItem can have many MenuItems as children, and of course it can have a parent MenuItem itself. Since the way records oughtta be retrieved is mostly dictated by these semantics, and yet the code cannot determine for you which direction to go, you can use mode to specify this. Zend uses two methods for fetching related records: findParentRow() and findDependentRowset(). You can specify either one with the keywords parent and dependent, respectively.
Passing conditions to bind queries If you wish to filter the related records further, pass your conditions along as a Select object:
<?php
$modelBlogPost->bindModel('Model_Tag', array(
'conditions' => $modelTag->select()->where('created > 2010-0-0')
));
?>
Note that the select object comes from the other model.
In HABTM cases, internally an 'm' alias is used. Therefore, if you need the table name, you have to use 'm':
<?php
$modelBlogPost->bindModel('Model_Tag', array(
'conditions' => $modelTag->select()
->from(
array('m' => $modelTag->getName()),
array('id', 'name')
)
)
);
?>
In above example, we're adding the conditions to specify which columns we want to retrieve; this is done with Zend's from().