Filter Out Unnecessary Recursive Relationships

By Mark (marklap)
Add a small function to your AppModel to filter out those recursive relationships that are unnecessary for a particular controller action.
I wrote this using the following articles for references. Thanks folks, they helped me write this snippet in about 15 minutes.

unbindAll by cornernote Keeping bindModel and unbindModel out of your Controllers by TommyO An improvement to unbindModel on model side by mariano
I didn't need the full functionality of some of these solutions. I just needed a way to quickly and succinctly filter out a particular model's associations.

Please comment with your observations, corrections, and/or comments.

Add this function to your AppModel:

Model Class:

Download code <?php 
class AppModel extends Model{

    
/**
     * Performs an 'unbindModel' on an array of associations
     * 
     * @param array $bindings An array of model associations to unbind from current model
     * @return null
     */
    
function filterBindings($bindings null) {
        if (empty(
$bindings) && !is_array($bindings)) {
            return 
false;
        }
        
$relations = array('hasOne''hasMany''belongsTo''hasAndBelongsToMany');
        
$unbind = array();
        foreach (
$bindings as $binding) {
            foreach (
$relations as $relation) {
                if (isset(
$this->$relation)) {
                    
$currentRelation $this->$relation;
                    if (isset(
$currentRelation) && isset($currentRelation[$binding])) {
                        
$unbind[$relation][] = $binding;
                    }
                }
            }
        }
        if (!empty(
$unbind)) {
            
$this->unbindModel($unbind);
        }
    }
}
?>

Then in your controller use the 'filterBindings' function:

Controller Class:

Download code <?php 
class PostsController extends AppController {

    var 
$name 'Posts';

    function 
index() {
        
$this->Post->recursive 2;

        
$this->Post->filterBindings(array('Comment''Rating'));
        
$this->Post->User->filterBindings(array('Status'));
    }
}
?>

 

Comments 646

CakePHP Team Comments Author Comments
 

Comment

1 How is this easier than Bindable behavior

?

For example, what if your Post model changes? You would have to go back through all your code to find filterBindings() and re-write them to include any changes in Post's relationships.

Using Bindable behavior, you INclude all the models you need, rather than EXcluding them. Plus, you can do neat things like query based on HABTM conditions, select only certain fields from related models, and much more.

Plus, it sets the level of $recursive AND returns the value when you make a call to restrict().

I would suggest looking into Bindable if the above solution is too limited for your needs.
Posted Apr 21, 2008 by ambiguator
 

Comment

2 This is for version 1.1.x

The Bindable behavior looks great and I'll investigate it for when I upgrade to 1.2.x. Until then, this function works perfectly for my needs.
Posted Apr 29, 2008 by Mark