Filter Out Unnecessary Recursive Relationships

by 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:

<?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:

<?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'));
    }
}
?>

Report

More on Tutorials

Advertising

Comments

  • marklap posted on 11/18/09 03:38:31 PM
    This was a quick fix for me when I was on 1.1.x. With 1.2.x's Containable behavior, this code is pretty irrelevant. Unless of course you don't want to import the Containable behavior for some reason.
  • rangi500 posted on 11/13/09 05:57:15 AM
    Thanks for the snippet, this works great. I'm on CakePHP 1.2.
  • aaron posted on 04/21/08 12:35:48 PM
    ?

    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.
    • marklap posted on 04/29/08 03:59:40 PM
      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.
login to post a comment.