Oct292007

ExpectsBehavior, model unbinding in CakePHP 1.2

UPDATE: the first beta version has been released, and renamed to Bindable Behavior. Check it out at its bakery tutorial Bindable Behavior: control your model bindings.

It’s been some time since I’ve done any work on expects, and while enjoying the incredible set of cool features CakePHP 1.2 pre-beta is giving us all, I decided it was time to let expects meet 1.2. My new baby is called ExpectsBehavior. As its 1.1 predecessor, its main goal is to provide a wrapper for CakePHP’s unbindModel function, to let the developer specify what bindings (model relationships) he’s expecting right before a find. At the same time, I needed some new features to be added, some of them courtesy of the previous brain work Felix did on his very cool Containable behavior.

So what are some of these cool new features I’m talking about?

  • Parameter notation flexibility: you can choose different ways on how to specify the models you need. Whatever is sexier for you!
  • Calling methods: you can use the old way (calling Article->expects() right before your find), or use the newly CakePHP find notation with embedded parameters for the behavior, specifying your expects setting right on the Model::find() call.
  • Override binding settings: tired of having to do a bindModel() to override some binding settings (such as limit, order, offset) right before your expects call? Want to only get certain fields of a related model, instead of all of them? Don’t stress! ExpectsBehavior allows you to override these settings easily.
  • Auto recursivity: by default, ExpectsBehavior will determine the necessary recursivity needed to fetch the models you specified, and will set the main model recursivity accordingly. This feature can be disabled via a behavior setting.
  • Warnings: if you enable a behavior setting, ExpectsBehavior will issue notices when specified bindings do not really exist. By default this setting is disabled.
  • Thorough testing: I’m working very hard in adding tests for almost every conceivable aspect of the ExpectsBehavior. I’m already at 433 asserts, and counting! All succeeding, naturally ;)

Let’s start with the basics: parameter notation. ExpectsBehavior allows you to use two types of alternative notations when defining the bindings you are expecting: dot notation, and depth notation. Dot notation comes from expects 1.1, while depth notation is an alternative way where you specify the models using associative arrays. Let’s start with some samples (both calls will produce the same result):

// Dot notation

$this->Article->expects('Category', 'Comment.User', 'Tag');

// Depth notation

$this->Article->expects(array('Category', 'Comment' => 'User', 'Tag'));

Ok, let’s get a little deeper:

// Dot notation

$this->Article->expects('Category.Section', 'Comment.User.Profile', 'Tag');

// Depth notation

$this->Article->expects(array('Category' => 'Section', 'Comment' => array('User' => 'Profile'), 'Tag'));

What about mixing them up?

$this->Article->expects(array('Category' => 'Section', 'Comment' => 'User.Profile', 'Tag'));

Cool, huh? Now, with calling methods you can still call expects the way we’ve just seen (the old way), or use the new, cool way: embedded parameters. Instead of doing:

$this->Article->expects(array('Category', 'Comment' => 'User', 'Tag'));
$result = $this->Article->findAll();

Why not just do:

$result = $this->Article->find('all', array('expects' => array(
	'Category', 'Comment' => 'User', 'Tag'
)));

Wait, does that really work? Yeah it does! Really? Of course! But don’t go anywhere, there’s more. Amongst the features I mentioned you can now override binding settings. Let’s see some code! Assume we just want the fields ‘username’, and ‘email’ for the User binding on our previous call, so we simply change it to:

$result = $this->Article->find('all', array('expects' => array(
	'Category',
	'Comment' => array('User' => array('username', 'email')),
	'Tag'
)));

Or if you don’t like seeing so many arrays, use the embedded field notation:

$result = $this->Article->find('all', array('expects' => array(
	'Category',
	'Comment' => 'User(username, email)',
	'Tag'
)));

What about mixing fields and inner models? Let’s bring up the Profile attached to a User, and the Friend the user’s got:

$result = $this->Article->find('all', array('expects' => array(
	'Category',
	'Comment' => array('User' => array('username', 'email', 'Profile', 'Friend')),
	'Tag'
)));

What about other settings? Like limit, and order? Sure, no problem. Say we want to get only the first 5 tags related to the articles, and order them by their field tag. Then let’s change the above to:

$result = $this->Article->find('all', array('expects' => array(
	'Category',
	'Comment' => array('User' => array('username', 'email', 'Profile', 'Friend')),
	'Tag' => array('limit' => 5, 'order' => 'tag ASC')
)));

I’m not yet releasing it since I want to add further testing, but I will be posting the sourcecode on a live server very soon. So stay tuned, and until then I welcome your feedback.

Related posts:

  1. Limiting the associated models returned with CakePHP
  2. Modelizing HABTM join tables in CakePHP 1.2: with and auto-with models
  3. Using Configure in CakePHP applications


Leave a Comment

13 Comments to "ExpectsBehavior, model unbinding in CakePHP 1.2"

  1. Oct292007 at 11:35 pm

    sarimarton [Visitor] wrote:

    Thanks for that, looking forward to it.

  2. Oct302007 at 12:27 am

    Geoff Ford [Visitor] wrote:

    Sold! Can’t wait to start using this Behaviour.

    Geoff

  3. Oct302007 at 5:59 am

    nao [Visitor] wrote:

    Great! I make an model behavior with similar features and some others. Difference is I add ‘*’ syntax. It allow to don’t unbind child of a assoc in a branches. My behavior support too self join (it repeat rules in this case until max recursive level). Finaly, It support support negative rules with ‘!’ syntax.

  4. Oct302007 at 9:45 am

    dericknwq [Visitor] wrote:

    Aye, release it soon! :) Will be good if there are ways to make it permanent to work with Controller::paginate. Also, could have a restore original association method! In that case, we can have a permanent call when using paginate, then restore the original associations for the other lines of code after it.

  5. Oct302007 at 2:07 pm

    mariano.iglesias [Member] wrote:

    @dericknwq: There’s a method to restore the original associations right in the behavior. You would just do: $this->Article->resetExpects(). About paginate, it may even get simplier than that in the near future, though you could use ExpectsBehavior now by implementing the paginateCount() and paginate() method on your models.

  6. Nov062007 at 5:34 pm

    gonzalo [Visitor] wrote:

    Excellent work, really waiting for this!
    Do you expect that in the final release the conditions setting of the relationship could be overrided too? Or the only ones modifiable (¿?) are limit, order and offset?

  7. Nov072007 at 1:32 am

    mariano.iglesias [Member] wrote:

    @gonzalo: currently these are the settings that can be overriden through expects: ‘conditions’, ‘fields’, ‘limit’, ‘offset’, ‘order’.

    I am already committing the code to a public SVN and preparing the tutorial, so it will be on very soon.

  8. Nov122007 at 6:56 pm

    @martin [Visitor] wrote:

    Siempre brindando una bocanada de aire fresco a la comunidad de Cakephp. No hace falta decirte que muchos te seguimos los pasos.
    Siempre hablando de behaviors, podes dar un consejo para solucionar los problemas que surgen con los behaviors y la recursividad en las asociaciones de modelos?

    Un abrazo.

  9. Nov202007 at 2:06 am

    Aaron Shafovaloff [Visitor] wrote:

    How is this coming along? Will it be done soon?

  10. Nov202007 at 10:55 am

    mariano.iglesias [Member] wrote:

    @Aaron: yeah, actually I have it committed to a publicly available SVN server, but I have not yet released it since I’m finishing the tutorial. But for all of you who are interested in an early release (I won’t publish this anywhere else) here’s the SVN address from where you can checkout expects:

    svn co https://cake-syrup.svn.sourceforge.net/svnroot/cake-syrup/expects

    Or browse the expects SVN branch online:

    http://cake-syrup.svn.sourceforge.net/viewvc/cake-syrup/expects

    As you’ll see there are two files:

    * app/models/behaviors/expects.php – The ExpectsBehavior
    * app/tests/cases/behaviors/expects.test.php – The test cases for ExpectsBehavior

    The code is stable, but since I have not yet finalized its documentation consider it to be an early release.

  11. Nov212007 at 8:59 pm

    landor [Visitor] wrote:

    Using nightlies rev 6030, php5, I get a bunch of warnings:

    Warning (2): Illegal offset type in isset or empty [APP/models/behaviors/expects.php, line 63]
    Warning (2): Illegal offset type [APP/models/behaviors/expects.php, line 65]
    etc…

    referring to
    $this->__settings[$Model->alias]
    because $Model->alias is an array.

    I am not using it extensively, but it seems to be working despite the warnings.

  12. Nov212007 at 9:09 pm

    mariano.iglesias [Member] wrote:

    @landor: Model::$alias an array?? Are you declaring that variable yourself? It is used internally by CakePHP core, and it should *allways* be a string.

    Can you report a new bug ticket on the project page at:

    http://sourceforge.net/tracker/?func=add&group_id=209331&atid=1009286

    So I can keep a closer track of it? Also I’d really appreciate if you can attach the models with which that is happening to you (model declarations + bindings). Did this happen while you were running the test case or just on your own models?

    Thanks! :)

  13. Nov232007 at 4:53 pm

    mariano.iglesias [Member] wrote:

    @all: UPDATE: the first beta version has been released, and renamed to Bindable Behavior. Check it out at its bakery tutorial:

    Bindable Behavior: control your model bindings

 
Powered by Wordpress and MySQL. Clauz's design for by Cricava