RSS
 

Posts Tagged ‘Behaviors’

More cakephp 2.x infos and 3.x notes

22 May

Behaviors

I just recently found out that the attach() and detach() methods I have always been using seem to be deprecated (or at least only available for BC) – and that one should probably use load() and unload() from now on.
That is sure something I will have to get used to.

Many new features in 2.2

It is worth reading the migration guide on this one. The logging has greatly improved, also the Error Handling, the CakeEmail lib and CakeTime (finally with timezone handling).
A very new feature just recently introduced is the validator object to better interact with the model’s validation rules.

I already started switching some of my apps to 2.2 – although it is still beta it doesnt mean one cannot use it.
It might not be recommended for high profile websites just now. But in most cases it will run at least as stable as 2.1. Only the new features might still be kind of buggy. But since you don’t use them yet you will be fine. But due to a great test case coverage there shouldn’t be too many surprises for your live apps -even if you start using some of the new features.

What I really am looking forward for in 3.0

Namespaces

Of course! Hopefully it will help to remove some of those many collisions we still have in 2.x with class names.

Better approach on aliasing

As outlined in this ticket aliasing as well as correctly merging is broken in the current 2.x version. I fixed it and applied it locally. Unfortunately, the devs are not willing to accept the change as useful fix. I also prosposed bootstrapped aliasing which would make most sense. If declared this early we can avoid conflicts in the controller level.

Better folder naming scheme

As outlined in my proposal @ http://cakephp.lighthouseapp.com they naming scheme for 2.x creates some conflicts – especially in the View folder.
Those should be resolved for 3.x.

Long overdue bug fixes

  • Folder::merge (I applied that fix manually and locally)
  • Containable recursion (also applied manually)

and some minor other ones

Indentation for method comments

Currently they are still not indented. But since the methods are indented (one tab), their comments should be, as well – so both are on the same level. I do that already on the user land site (just as most other php code out there) and hope this will be fixed in 3.0. It is annoying if you want to copy and paste methods from one to another. Lots of indentation correction is necessary.

PSR Framework Standards (or: what I am not so much looking forward for)

Cake2.x already tries to comply with the Psr-0 standard which is about filename conventions in a framework. And the Psr-1 standard is fine, too.
Recently, psr-1 and psr-2 have also been approved as standards. Although many of it reflects the way cake handles it and as it should be there are some major flaws. And I am glad that cake doesn’t follow them (yet).
For starters, the biggest mistake ever in this standard: using spaces for indentation instead of tabs. That’s just so awfully wrong and 19th century that I better don’t even go into any details here. It is sad that even some core developers who tried to reach those guys didn’t succeed in convincing them that they are making a huge mistake.
Secondly the way braces are set for classes and methods (in a new line instead of the same) which stands in contrast to the way it is done for conditional statements where it actually is on the same line. In the end an ugly inconsistency.

The (in my opinion wrong) PSR-1 standard states:

class Foo
{
	public function class bar() 
	{
		if ($var) {
			// ...
		}
	}
}

The correct bracing (which cake fortunately uses) is:

class Foo {
	public function class bar() {
		if ($var) {
			// ...
		}
	}
}

It not only reduces the vertical length (and therefore the readability especially for larger classes and methods) but also keeps the bracing consistent throughout the document.

But not all is bad. There are a few good approaches. And if all those frameworks grow together a little bit due to a common standard it will help the cross-compatibility in the long run.

 
No Comments

Posted in CakePHP

 

Introducing two CakePHP behaviors

05 Jul

Today I want to introduce two new CakePHP behaviors.

Jsonable Behavior

This is not so new, of course. Already existed as a basic version in the Bakery.
I enhanced it to work with more than just plain arrays and added some more functionality.

The behavior can be found in the Tools Plugin.

In my first scenario where I used it, I had a geocoder behavior attached to the model which returned an array. I wanted to save all the returned values, though, for debugging purposes in a field "debug". By using the following snippet I was able to do exactly that.

public $actsAs = array('Tools.Jsonable' => array('fields' => array('debug'), 'map' => array('geocoder_result'));

I could access the array in the view as any other array since the behavior re-translates it back into an array on find().
Note: the mapping option is useful if you want to rename certain fields. In my case the geocoder puts its data into $this->data[‘Model’][‘geocoder_result’].
I might need to access this array later on in the model. So I "jsonable" it in the "debug" field for DB input and leave the source field untouched.

That’s all very nice. But what if needed something more frontend suitable. I want to be able to use a textarea field where I can put all kinds of params which will then also be available as array afterwards (as long as you are not in edit mode, of course).

In our add/edit actions we need to switch to param style:

$this->Model->Behaviors->unload('Jsonable');
$this->Model->Behaviors->load('Tools.Jsonable', array('fields' => 'details', 'input' => 'param', 'output' => 'param'));

The form contains a "details" textarea field. We can insert:

param1:value1|param2:value2

In our views we get our data now as array:

array('Model' => array(..., 'details' => array('param1' => 'value1', 'param2' => 'value2')));

And, of course, as third use case we can also simulate an ENUM by using:

$this->Model->Behaviors->unload('Jsonable');
$this->Model->Behaviors->load('Tools.Jsonable', array('fields' => 'tags', 'sort' => true, 'input' => 'list', 'output' => 'list'));

Note: The default value in the model itself still needs to be array in order to transform them into a list on find()!
That’s why we only override them in the form views.

In our textarea we can now type:

dog, cat, cat, fish

In our views we would result in (var $data[‘Model’][‘tags’])

array('cat', 'dog', 'fish');

Note the cleanup automation you can additionally turn on/off.
There are more things to explore. But I will stop here for now.

Yes – you could make a new table/relation for this in the first place. But sometimes it’s just quicker to create such an enumeration field. Bear in mind: It then cannot be sorted/searched by those values, though.
For a more static solution take a look at my Static Enums.

Confirmable Behavior

This I invented a while ago working on a registration page. After I needed the same functionality on other sites, as well, I started to build a behavior out of it. Now I don’t have to repeat myself anymore.
On Github you can find the Confirmable behavior.

Example Usage in an action:

// if posted
$this->Model->Behaviors->load('Tools.Confirmable', array('field' => 'confirmation', 'message' => 'My custom message'));
$this->Model->set($this->data);
if ($this->Model->validates()) {
	// OK
}

In the corresponding view of this action:

echo $this->Form->input('confirmation', array('type' => 'checkbox', 'label' => __('Yes, I actually read it')));

The user has to check the toggle field provided. Otherwise validation will fail.

Some notes on behavior development

Make sure you return the right boolean value in those beforeValidate() methods etc.
Usually this should be TRUE even if it fails.
The reason is you want to display all errors at once in the form. If you return FALSE too soon, the other validation methods won’t get triggered and you have a staged validation which is a bad thing.
So return TRUE. And don’t worry, as long as there are errors the save method won’t get triggered.

As you can see the settings are always "per Model->alias". This way multiple models with the same behavior won’t interfere which each other (since they all use the behavior instance – yes, that’s the CakePHP way of saving resources, I guess).

Update 2013-08

I upgraded the examples from 1.x to 2.x code.

2014-01-22

Modified the methods to 2.4/2.5 syntax: attach=>load and detach=>unload

CakePHP 3

This article is 2.x only.
For CakePHP 3 please see the 3.0 Tools Plugin documentation for the upgraded JsonableBehavior.

 
2 Comments

Posted in CakePHP