Return null vs return void

05 Oct

The other day I had a discussion about that, and why important open source frameworks like CakePHP use void in @return doc tags when void and null are code-wise totally identical.
So here my reasoning why it is a good idea to make a distinction:

Help the developer, not the machine

We already discovered that it doesn’t help the machine to make the difference.
So if anything, it would help the developer. So does it? Yes, it does (as with all coding standards, these things are there to make it easier for the developer and avoid human error).
In fact, most modern IDEs would light up the function like a Xmas tree if you tried to use a return void function value.

The following would be marked yellow (warning) right away:

 * @return void
public function doSth() {
 * @return void
public function badCode() {
    return $this->doSth(); // This would be marked yellow

So it helps the developer to not try to use return values of those methods.
This would not happen without the explicit @return void annotation.

See the following screenshot of what PHPStorm, for example, can now help us with:


And also the other way around:


Bottom line:
void as pseudo type is not used to state that we return nothing/null (which is still true from a value point of view), but it is used to state that we should not expect anything (not trying to use it’s return value in any way).

Other reasons maybe

Be explicit

If you just see the following code, you might not know immediately, if someone just forgot the return type statement. If it was there from the start you would automatically know.

 * @param string $param Param
public function doSth($param) {
    // very long code block...

Be consistent

Some methods end up to not have any doc block, just because the doc block would have the return void part:

 * @param string $param Param
public function doSth($param) {
public function doSthElse() {
 * @param string $param Param again
public function doSthAgain($param) {

Especially if you don’t use descriptions this is quite inconsistent.

Part of PSR-5 and PHP RFC

It is also part of the upcoming PSR-5 standard.
To point out that is not just fiction πŸ˜‰
Even though they state it to be optional (omitting that type altogether would also be valid, of course).

As long term goal then, once PHP RFC void_return_type is implemented, we can easily use a script to adjust the code.
Without being explicit this will not work out. So better use the best practice approach now already and save yourself tons of work in the long run.

Automated checking

It will be easier to automate and verify this via code sniffer or other tools when explicitly set, whereas the omitting does not tell if it was on purpose or just forgotten.
Especially since it forces to code more return type aware from the beginning (see the following part on potentially hidden issues around mixed return types).

Implications to consider

This means you should also use it consistently through-out the code base. Here a few things to keep in your mind.

Whenever you return multiple types (mixed), do NOT use void, use null instead.
The reason is simple:
You are returning an object or not (null), but you are using/checking the value of it afterwards, so returning void would be a lie (or trying to check on a void return result would be "pointless").

 * @param Object $object The object.
 * @return Object|null
public function doSthAndGiveMeSth(Object $object) {
	if ($object->isNotValid(()) {
	    return null;
	// ...
 * @param Object $object The object.
 * @return void
public function doSthWithIt(Object $object) {
    $returnValue = $this->doSth($object);
    // ...

This is also true for returning early inside those methods/functions.

Also always explicitly return null at the end of a "non-void" method, if nothing else is being returned.

For returning early in void methods, use the following:

 * @param string $param Param
 * @return void
public function doSth($param) {
	if ($param === null) {
	// ...

An explicit return; statement at the end of those methods is never necessary (= should not be used therefore) and implies void when omitted.

Do not use return statements for constructor __construct() and destructor __destruct(), as both per definition cannot return anything.
This is the only exception made.

Adjusting your IDE

You can adjust IDEs usually to automatically add @return void as default.

For PHPStorm go to Settings -> Editor -> File and Code Templates -> Includes (tab) -> PHP Function Doc Comment.
Replace the template with:

#if (${PARAM_DOC} != "") ${PARAM_DOC}
    #if (${TYPE_HINT} != "void") *
 * @return ${TYPE_HINT}

Other implications


Some frameworks use special methods that can return an object, or nothing, e.g. controller methods as actions.
In that case it can be convenient to not have to return explicit nulls all the time at the end of each action.
Maybe, in some rare use cases one could use null|void (and then Response|null|void) as a way to allow omitting the explicit returns but to show that it would actually allow checking for the returned result afterwards. The IDE won’t complain then, either.
That should definitely stay the exception to the rule then, of course.

Building fluid interfaces

Once you use use a lot of @return void you end up using their methods appropriately – which implies that you don’t use the return value at all (not permitted).
That concludes that you could, basically without breaking the API, start returning the object itself ($this as in @return self). This transforms the class into fluid interfaces which allow method chaining then.
So look for those return types in your classes and think about where those could be part of a fluent interface pattern. Might not always be a good idea, but could very well be in some places.

Further reading

Take a look at php-void-much-ado-about-nothing.

It is also part of PSR-2-R Additions.

Update 2015-11

So the void RFC has been approved. Will be part of PHP 7.1 then πŸ™‚

3.60 avg. rating (74% score) - 5 votes
No Comments

Posted by Mark in PHP


CakePHP Tips 2015

13 Sep

Most tips are for 2.x and 3.x as they have been applied to both versions.

Complex radio inputs

A while back I posted a tip about deep array options for select input form fields.
With my recent path for 2.6 and 3.0 (>= 3.0.8) this is now also possible for radio() fields:

echo $this->Form->input('Model.field', [
	'type' => 'radio',
	'legend' => false,
	'div' => false,
	'options' => [
		'1' => ['name' => 'Option A', 'title' => 'A Title'],
		'2' => ['name' => 'Option B', 'data-foo' => 'bar']


As of now, there is no way to directly disallow sort fields of pagination views.
There is a hack in 2.x to workaround this, though. Just set the whitelist to a non-existent field:


This way the whitelisting is triggered and no valid field can be found. Mission accomplished.

In 3.x (>= 3.0.8), finally, we have an easy way of doing this, by passing an empty array for sortWhiteslist:

'sortWhitelist' => []

Not passing any whitelist will just not trigger the whitelisting at all.

Using the 3.x Migrations plugin for your 2.x app

I have some rather large 2.x apps that will not be migrated any time soon. But I at least want to leverage some of the 3.x stuff already where possible.
So I can include subsplits of the 3.x version via composer.
But for CLI console scripts and the migrations plugin this does not work.
I don’t want to use plain SQL upgrade files, though. And for any other migration solution I would probably also need some third party tool.
Why not going with what CakePHP 3.x seems to be perfectly bundled with? The Migrations plugin πŸ™‚

So inside my 2.x app I create a subfolder upgrade where I put a very basic composer.json:

"require": {
	"cakephp/cakephp": "dev-master",
	"cakephp/migrations": "dev-master",
	"cakephp/bake": "dev-master"
"require-dev": {
	"cakephp/debug_kit": "2.*"
"autoload": {
	"psr-4": {
		"App\\": "src"
"autoload-dev": {
	"psr-4": {
		"App\\Test\\": "tests",
		"Cake\\Test\\": "./vendor/cakephp/cakephp/tests"

I basically check out the 3.x version in a subfolder along with the 2 plugins I need.
I also make sure, the cli folder and the config folder are present and working.

Then I modify the app.php to automatically pull the DB credentials from my root Config/database.php.
Since I don’t want to duplicate the configs.

$file = dirname(dirname(__DIR__)) . DS . 'Config' . DS . 'database.php';
if (!file_exists($file)) {
	throw new \Exception('Cannot find database.php');
$content = file_get_contents($file);
preg_match('/\'database\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$database = !empty($matches[1]) ? $matches[1] : '';
preg_match('/\'login\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$username = !empty($matches[1]) ? $matches[1] : '';
preg_match('/\'password\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$password = !empty($matches[1]) ? $matches[1] : '';
preg_match('/\'host\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$host = !empty($matches[1]) ? $matches[1] : 'localhost';
return [
	'Datasources' => [
		'default' => [
			'host' => $host,
			'username' => $username,
			'password' => $password,
			'database' => $database,

I can verify if it all works by running bin/cake bake migration_snapshot Init to make a snapshot of the current DB schema in the new migration code.
This will also automatically mark this migration file as migrated.
Now I can simply add more migration files with bin/cake migrations create {Name} and then migrate the DB via bin/cake migrations migrate.


2.67 avg. rating (61% score) - 3 votes
No Comments

Posted by Mark in CakePHP


CakePHP Meetups

19 Jun


Meetups are a great opportunity to get in touch with other companies or people that use CakePHP.
It is a good place to share experiences and find people even that might have similar interests or who could even join your projects.

The CakeFest is only one a year, and usually not around the corner from you, meetups can be a regional thing in your city or nearby.

CakePHP Meetups Germany

We just had a new meetup this month, and it was quite a crowd, 20+ people attended.
CakePHP devs not only from Berlin attended, but due to the IPC conference nearby also some developers from further away joined in.

The talks where mainly about how companies use CakePHP, and what experiences they made so far.
My talk was mainly about how to upgrade as smoothly as possible to CakePHP 3.x.
The slides can be found here: german-cakephp-meetup-3-berlin.

Someone posted on twitter about it: dopitz/status/608683826932543488.
Good thing I didn’t wear my worn-out shirt πŸ˜›

Oh, and there is a group pic (some left already again, though): HeikkiPals/status/610475391015383041.

Findings so far

It turned out to be quite successful here in Berlin if held only once every 3-4 months. Too regularly and people miss out.
It also helped if some interesting topics/talks were provided and communicated before-hand. An extra bonus would be a prominent speaker, but
that is not always that easy to organize.

Overall, 20+ people is a good standard already and hopefully more and more devs also join us in real life in the future.

Other meetups world-wide

Check out the awesome-cakephp list regarding meetups in USA (NY), NL, FR, …

Other frameworks can do it, why shouldn’t we? πŸ™‚

Join in

If you are from Germany (doesn’t have to be Berlin) and you want to either attend an existing meetup event or create/host your own one, see

Send your ideas for a 20-30 min talk, propose some discussion topics and be part of the CakePHP community!

3.67 avg. rating (76% score) - 3 votes
No Comments

Posted by Mark in CakePHP


CakePHP 3.0 Migration Notes

06 Jun

Trying to migrate my CakeFest app for this year’s event, I made some notes regarding the upgrade process from 2.x to 3.x.
I completed them during the upgrade of my Sandbox app to 3.0. And adjusted them after RC2 and 3.0.0 stable again while upgrading 2 more apps and 5+ plugins.

Initial steps and requirements

The following were given in my case:

  • The app was already composered (as it should be for all CakePHP 2 apps) and thus "composer" was already available
  • I used a 2.x setup with ROOT dir as APP dir directly (which seemed to cause some trouble later on)
  • I used GIT for version control and supervise each upgrade step (which also caused some trouble)

Also make sure you covered the following reading material:

As a side note: It is also wise to follow the 3.0 development, read the PRs and proposed as well as recent changes.

Let’s go

By the time I wrote this I still had to tweak and fix the Upgrade tool along with it, so bear with me if something is not perfectly in sync here.

I first made sure I got a clean 2.x app with the latest (right now 2.6) changes, as outlined in previous posts regarding "how to prepare 2.x apps for 3.x".
I also used a "AppUsesCorrection" tool I have written to move all inline App::uses() statements to the top of the file. This was a left over from earlier days and will
screw up the files if not taken care off.

I also started to use the Shim plugin a while back for all my 2.x apps to make sure I already shimmed as much as possible towards 3.x, so the now required changes are minimal. If you already know you want to upgrade sooner or later, save time and shim "ahead".

Then I basically downloaded and initialized the Upgrade tool and ran the all command on my app and plugins separately.
In case something goes boom, better run the commands individually and verify the changes after each command (and commit them away).

Afterwards I adjusted my composer.json file for 3.0 and used composer update to get all new dependencies.
Here you should also make sure all dependencies like plugins are available as 3.0 versions, otherwise temporally remove/exclude them for now if possible.
Also don’t forget the new autoload and autoload-dev parts in the composer file.

A first try run revealed that I had still a lot of manual work to do in /config first:

  • config/app(_local).php
  • core.php (deprecated) => bootstrap.php
  • database.php (deprecated) ) => app(_local).php
  • routes.php

A tip here: IMO it is wise to not directly modify app.php as changes along the line will be harder to spot.
Instead I keep the file as it is (default) and just use a second one app_custom.php on top to overwrite/complete it where necessary.
I also use a third app_local.php, which is not under version control (.gitignore), to store non-commitable stuff like keys, salts, passwords etc.

Configure::load('app', 'default', false);
Configure::load('app_custom', 'default');
Configure::load('app_local', 'default'); // Not under version control

I found a lot of namespaces to be missing, as a lot of App::uses() have been left out in 2.x. It still worked there, as without namespaces it only needs it once per dispatching. But now it fails hard. So if you didn’t add the missing ones back in 2.x, you need to do that now at least.
I developed a tool to do that, the opposite of the unused_use fixer pretty much. This is very complex though. as it is not
always clear what package the use statements need to come from. It needs some config overhead.

I also had to remove the table prefixes as they are not supported in 3.x using my new CakePHP 3 Setup plugin DbMaintenance shell command cake Setup.DbMaintenance table_prefixes. It removed them in a few seconds. Afterwards my Table classes were able to find the tables again.

Afterwards I already tried to access a public page. Got quite a few things I had to manually take care of now:

Manual changes

Change public $uses = array('User'); to public $modelClass = 'User';. If there are multiple statements, this has to be resolved afterwards on top, using
$this->loadModel() etc.


The routes file will most likely also have to be adjusted by hand. The (admin) prefixes are the change that sticks out most.
But it is more repetitive than difficult to adjust the routes.
Bear in mind that you can easily set the fallback route class to InflectedRoute here first to handle them just as 2.x did:

Router::defaultRouteClass('InflectedRoute'); // Use DashedRoute for new 3.x projects


All the URLs usually are now more case sensitive (and CamelCased/camelBacked)

// Before
Router::url(['admin' => true, 'plugin' => 'my_plugin', 
	'controller' => 'my_controller', 'action' => 'my_action'])
// After
Router::url(['prefix' => 'admin', 'plugin' => 'MyPlugin', 
	'controller' => 'MyController', 'action' => 'myAction'])

Also make sure, you dont use the prefix values directly (admin, …) anymore, but the prefix key itself:

// Before
'loginAction' => ['admin' => false, 'plugin' => false, 
	'controller' => 'account', 'action' => 'login'],
// After
'loginAction' => ['prefix' => false, 'plugin' => false, 
	'controller' => 'Account', 'action' => 'login'],

E.g. for the AuthComponent config here. Otherwise it will redirect you to the prefixed URL instead as admin is not recognized anymore.


The auth code in the AppController and login action needed to be adjusted.
In the controller, it is not via properties anymore, but Auth->config(). The login action needs identify() and setUser() now.

Array => Entity

With the array to entity changes a lot of view files cannot be fixed with the Upgrade shell, and stuff like echo $profile['User']['id'] has to be refactored into echo $profile->user['id'], for example.
As $user['User']['id'] would be $user['id'] now, there are changes across all MVC layers to be applied in order for the functionality to work again as expected.


For all my own custom replacements I collected them and made a Custom task over time to avoid having to do this all over again across multiple apps or plugins.
I therefore forked the Upgrade plugin.

When working with date(time) fields I also had to do some special refactoring, as some older apps had 0000-00-00 00:00:00 stored as null/default value.
This is quite unfortunate, as with Carbone and Time class, this would create negative values, which blows everywhere.
So I created a Setup.DbMaintenance dates command in the Setup plugin to refactor those fields and their content into the proper value.

The same goes for foreign keys and '0' stored in wrong DEFAULT NOT NULL columns. With the Setup.DbMaintenance foreign_keys command you can also clean those up (DEFAULT NULL + NULL value).


It would be quite the task to rewrite the whole validation with all the models and their $validate properties. So here I just used the Shim plugin from above and kept the old syntax to save time. The same for relations and a lot of other model properties. It then only needed minimal adjustments, like adding 'provider' => 'table' for isUnique rule or changing notEmpty to notBlank.

Virtual fields

Mixing them with the fields array itself is not so easy anymore.
You can use closures to help out:

// For your find('all', $options) $options
'fields' => function ($query) {
	return [
		'jobtype', // Normal field
		'num' => $query->func()->count('*'), // COUNT(*)
		'fetchdelay' => $query->func()->avg('UNIX_TIMESTAMP(fetched) - IF(notbefore is NULL, UNIX_TIMESTAMP(created), UNIX_TIMESTAMP(notbefore))'), // Something more complex
		'age' => $query->newExpr()->add('IFNULL(TIMESTAMPDIFF(SECOND, NOW(), notbefore), 0)'), // Custom expression


The Locale folder is inside src, but the subfolders changed quite a bit. It is now flat, just two-letter country codes, for Germany the po file would be located in /src/Locale/de/ now (instead of .../Locale/deu/LC_MESSAGES/).

View ctps

These template files also have to change quite a bit.
For starters, the above array to entity conversion introduces a lot of change.
Also, all static calls now have to be handled by either importing the classes via use ...; statement at the top of each file, or you can wrap them with a helper.
A quickfix would be to just class_alias() them, e.g. the Configure::...() calls would need a lot of use statements you can omit if you put the following in your bootstrap.phpfile:

class_alias('Cake\Core\Configure', 'Configure');

Now, all Configure::read() calls work again in the ctps.


If you don’t directly output your inline assets, but add them to the "scripts" block to be outputted together in the layout, you will have to change the method calls.
It used to be 'inline' => true/false, now it is:

$this->Html->css('jquery/galleriffic', ['block' => true]);
$this->Html->script('jquery/jquery.galleriffic', ['block' => true]);

In your layout ctp you can then keep the echo $this->fetch('css'); and echo $this->fetch('script'); part as it was in 2.x.

Tricky ones

Tricky as in "not ease to spot"…

The !empty PHP bug I mentioned a while back.
I had a pagination index view where I iterate over all users and display something else if there are none (yet). This fails, now, though, as the empty check will always return false:

<?php foreach ($users as $user) {} ?>
<?php if (empty($users)) {} ?>

The empty check needs to be this way in order to work as expected:

<?php if (!count($users)) {] ?>

Or, when you know it is a query finder object:

<?php if ($users->count()) {] ?>

Same with:

while ($records = $this->_table->find('all', $params)) {}

This will run endless now. Here either add ->toArray() or use a streamable result.

UPDATE Since recently (3.0.4?) you can also use ->isEmpty() as check on any Query or Collection object:

$result = $this->TableName->find()->...;
if ($result->isEmpty()) {}


I used the Shim plugin and the support for find(first) and find(count), but even then you need to make sure that for find(first) you don’t forget to adjust all those $options regarding keyField and valueField which are now required to be set if you plan on using non displayField values, as the "fields" list is ignored for it (used to work to filter on 2 fields and it automatically used those).

Magic/Dynamic finders

Careful with those, like findByUsername(). In 2.x. those returned find(first) results (limit 1 so to speak), in 3.x. those need an additional ->first() appended to have the same result.

Trait or Behavior?

You might run into this when refactoring your models and behaviors.
In 2.x behaviors had the problem that they didn’t work for non-primary models, and as such where often too limited and one probably tried to workaround it using traits.
In 3.x that limitation is gone.

I think the main idea behind behaviors keeps the same: If you want to dynamically attach and detach functionality to your models, this is the way to go. Traits are too static for this. Traits, on the other hand will be necessary if you want to cleanly overwrite Table methods, see the SoftDelete trait for an example. In that case you just can’t do this dynamically.

Additionally, behaviors can more easily be configured using built-in config() and they can be aliased easily. The downsite might be speed, which is neglectable, though.
So try behaviors first, then fallback to traits IMO.


All in all quite a lot of migration steps can be (partially) automated, which will help a lot for larger applications where it would just be super-tedious to do that manually on such a scale. But most of the ORM changes need manual code changes, which makes it really a time-intensive task for medium apps and above.
Using shims, coding wisely ahead of time, avoiding hacks or non-wrapper low-level functions, all those can help to ease migration. In the end you just have to swallow the bitter pill and get it over with. It is worth it!

3.33 avg. rating (71% score) - 3 votes

Posted by Mark in CakePHP


CakePHP 2.6 – and the end of the beginning

15 Mar

I was first thinking about the title "and the beginning of the end" – but that sounded a little bit too Armageddon. In fact, 2.x will probably still be around for years – and at least 2.7 will still be released some day (it is not impossible that there might even be a 2.8 …).
The title "and the end of the beginning" fits much better as it allows fresh projects and early migrations to already leverage the new 3.x milestone while the rest just sticks to the 2.x one a while longer.

So what does 2.6 and 2.7 mainly bring?
First of all they benefit a lot from 3.x backports.
Many of the new 3.x functionality has been and will continue to be backported to 2.x.

They also allow the chance to further cleanup the code-base and make the code itself more "3.x-ish". Some of that can be done by looking at how the new core does things, some of it can be achieved using Shims (Code bridges between two versions).
Some of those things became already clear from the dev-preview versions of 3.x – and my article around it.

A few basic things that are very useful in light of the above:

  • Make your 2.x code (app, plugins) PHP5.4+ (maybe also use short array syntax). It will make the upgrade process smoother
  • Remove deprecations and outdated ways of doing things
  • Stay up to date with the 3.x developments and how to best use that information for future proof 2.x development

My recent doings

First I made sure, every app is now running on latest 2.6 stable, and added a few more tests along the road.
Further I made sure relevant changes or new features in 3.x core are backported to the 2.x core and that I plan to migrate to those in my apps ASAP.

Plugin cleanup

I started to extract my super-fat Tools plugin into smaller chunks. Most recent split off is the Shim plugin as I had to acknowledge the fact that I mixed too many fixes/shims and new functionality, which is usually not the best thing to do.
So there it is: A Shim plugin to contain all the bridge code towards 3.x and a few fixes along with it. And a Tools plugin that builds on top of it and adds the actual functionality.
This was the logical thing to do. Most of the shims are not needed beyond 3.x, and as such they shouldn’t be in a more persistent plugin.


That brings me right to the next point: I looked into how to get 2.x apps closer to 3.x. Especially for lager code bases this really helps the migration to the next major version. Less necessary changes mean less change for breaking and faster upgrading results.

I ported flash messages to my 2.x version of FlashComponent and FlashHelper – including the syntactic sugar of $this->Flash->success($message).
This code will not have to be modified again at all when upgrading then.

Instead of the "mocking the hell out of it"-ControllerTestCase class I backported the IntegrationTestCase to 2.x which has a more sane approach on actual controller testing.
Using the syntax of 3.x in 2.x allows me to add a lot of new integration tests that will flawlessly work after the major version jump some day.

Password hashing

I migrated my 2.x apps from sha1 to state of the art PHP5.5+ password hashing (and the default in 3.x) – which can already work in 5.4, as well, thanks to shims. But I also needed to support existing passwords to provide BC.
So basically, I use the Shim.Fallback password hasher along with Shim.Modern and Simple ones to have a graceful fallback on old accounts and an auto-hash migration upon login. Each time a user logs in the new hash replaces the old sha1 one. Over time all users will be fully migrated and I can switch back to just Shim.Modern hasher directly (which is the Default hasher in 3.x by the way).

So after migrating to 3.x it will be:

  • Shim.Modern => Default
  • Simple => Weak

The latter is only relevant in case not all passwords have yet been migrated.

See my other article for details on how to implement them (via Passwordable behavior for example) or directly visit the Shim plugin documentation.

4.20 avg. rating (84% score) - 5 votes
No Comments

Posted by Mark in CakePHP


ACL – Access Control Lists – revised

06 Jan

With a focus on CakePHP application development.

Authentication vs Authorization

Those two are often confused. So here a little preface:

Authentication always comes first. It is about whether you are logged in or not. At this point it is not yet relevant who has access to what.
It is merely checked if the specific action/URL can be publicly accessed or needs authentication first.

After the authentication process, usually completed through some kind of login, the authorization decides on who can do what.
Here either roles or specific users are checked upon and the access is then either granted or denied.

Role Based Access Control (RBAC)

The easiest form of authorization is usually "role based access control", where you assign each other a role, and all that needs to be done is comparing
the user’s role (or roles in multi-role setups) to the required role for a specific action.
This can be realized with a single "roles" table and "role_id" in "users" table (or for multi-roles a "roles" and "user_roles" table) along with some table or file to store the
role/action relations.

Row Level Permissions

ACL is part of Authorization, the second step.
It is called "row level" access control, as it can go beyond just roles/actions combinations. Depending on the implementation it can also allow or deny specific users access to certain actions or records and make inheritable tree structures possible. So if you deny a certain user access to a node in the ACL tree(s), the sub-nodes are also prohibited by inheritance.
In its complex form (CRUD) it has even a flag for each type of action.
Such ACL trees can be quite complex to handle manually, and as such the tools provide you usually with some methods and CLI commands to make things easier.
So for the CakePHP core ACL there is even a plugin around some extra utilities for it.


Read in the docs how ACL works regarding ACO (Access Control Object) / ARO (Access Request Object).
Essentially, ACLs are used to decide when an ARO can have access to an ACO.
While this post mainly focuses on controlling access to actions and records, ACOs could be anything you want to control, from a controller action, to a web service, to a line in your grandma’s online diary. So it allows you to make anything "accessible".

Why ACL?

First of all you have to assess what kind of authorization is needed for your application. In 95% of all cases, a full stack row level ACL is not even needed, and simple roles per user would suffice.

The main questions boil down to:
a) Does it need row level permissions as in "I need to allow/deny certain actions – or even specific records – to certain users"? Sure this can’t this be done with more roles?
If so, then go for some ACL implementation. If not (and this often times cuts down the complexity quite a bit) use a role based one.

b) Does it have to be dynamic? For row level this usually has to be some DB driven solution. For roles it is sure nice to have some backend, but in my experience
it is often not really necessary, at least if it is not some kind of CMS, but a web application that has developers close by.

So it results in 3 different outcomes:

  • Row level + dynamic (=ACL)
  • Role based + dynamic (=RBAC dyn)
  • Role based + static (=RBAC stat)

Note that the 2.x core ACL also provides an INI based approach, but that is not recommended and somewhat useless.

Problems with ACL

When working with ACL back in 1.x and 2.0/2.1/2.2 one large problem with it was speed.
It is both slow in generating the aco/aro tree from all actions available throughout the project as well as checking them.
Depending on the implementation this can sometimes be the bottleneck of some controllers and their actions.
Especially with a larger user base and a not so small app this can probably get out of hand very soon.

When building the aro/aco trees the resulting tree structure table always seemed quite fragile to me. At least a few times it got, for some reason,
broken, and repair tools had to recover the tree structure. It is also very difficult to debug due to its complexity.
Additionally, you have to be very carefully with handling the data: You cannot just delete a user manually, or reset/truncate a table. It always has to go through the ACL channels for the tree to stay valid and filled with the right data.

Another problem I encountered when working with ACL:
It is locked to the DB, instead of the code base. So reproducing some issues with accessing actions locally can become tedious as you have a totally different user-base, controlled records and thus ACL entries. And if you deploy, but forget to update the ACL (or some action is not added for some reason) people will be locked out without indication/feedback. If you upload new actions, the permissions to it will not always be deployed along with it which feels counter-intuitive to me.
That applies for any dynamic (DB driven) permission setup, of course. So role based ones with an admin backend wouldn’t be off the hook here.
Using static and "file commited" permissions here assert that those always fit to the current code base. I found that a lot easier to maintain and debug.

Static RBACs ftw

For the last 6 years I have never needed ACL for any of my applications or have it found useful for a lot of others I have examined.
Defining some good roles was enough. And it was simple. Additionally, by keeping it static I neutralized the issue with the "not-in-sync" issues above.

I see a lot of people over-engineering that part without the (immediate) need for it.
So I would really keep it as simple as possible until the use case for more complex mechanisms arises.

ACL definitely has its use cases, and I wouldn’t dare to call it evil, but it needs to be thoroughly thought through and not applied blindly.
In case you need to use it, check here, if the ActionsAuthorize (Uses the AclComponent to check for permissions on an action level) suffices over CrudAuthorize (action -> CRUD mappings).

Alternatives to the CakePHP core ACL

Alternatives on row level

Often times you can’t get around some basic row level checking, e.g. when a user may only edit/delete his own posts.

The book has examples on how to add the currently logged in user to the data upon add action, and how to check for edit/delete if that user is the owner of that record.
This can be done using the controller’s isAuthorized() method. A little bit of hardcoding saves a lot of trouble here.

Alternatives to ACL in general

Role based

  • TinyAuth – static INI files by default but could be easily made DB driven or at least backend adjustable.


  • Controller based: ControllerAuthorize Calls isAuthorized() on the active controller, and uses the return of that to authorize a user. This is often the most simple way to authorize users. You can even mix role based with row level based auth if required.

Let me know if I forgot to list one. The full list of available plugins can be found at awesome-cakephp.

Last notes

In CakePHP3 ACL has been moved into a separate plugin, as it is just too much overhead for the core (since not so many actually use it) and doesn’t quite fit the 80%-rule therefore.

4.43 avg. rating (88% score) - 7 votes

Posted by Mark in CakePHP


Why CakePHP?

23 Dec

A Xmas post from Germany.

My last 6 years with CakePHP

I am now with CakePHP for over 6 years (wow.. time goes by!), the second half of it as core member. I started with it back in the days where 1.2 had just come out. I was just playing around back then.
Soon I started to write the first small 1.2 apps, mostly private stuff and ideas in my head. A "phonebook" app, "recipes" site, a "sandbox" for trying out Cake/PHP things, a small social network approach and few plugins on the side.

Not long after that I helped to develop the first real CakePHP app meant to be thrown out there for commercial purposes – and since then never stopped.
A little bit over a year ago I managed to finally upgrade even the last live app to the latest version 2.2/2.3 at that time.

Disclaimer: This is not meant to be a rip-off from josediazgonzalez’ why-to-actually-choose-cakephp/. It is my personal opinion why I have been sticking to this framework for the last years.

So why CakePHP in the first place?

There are alternatives, Symfony, Zend, Laravel, CI, …
But they all didn’t convince me in the beginning – and still don’t.
Mostly because as a beginner the first steps seemed and seems to be more complicated than with CakePHP. You need to do more to see actual and usable results.
But I don’t want to go into detail here too much.

A framework is an absolute must

At least as a beginner. But even as a pro you are sometimes happy to not have to modify all those "core changes" in your code when PHP, MYSQL or any other external script is used differently over time. You are also grateful for the community effort of being able to find and fix bugs as a group effort. And last but not least, you could never come up with all those great new features and ideas all on your own.
I found CakePHP to not only be community-driven but also very intuitive – over some time anyway.

CakePHP was already easy at the beginning

I already had PHP/MYSQL experience, but even without I might have succeeded with the first trial apps.
And although CakePHP has lots of conventions and opinions on certain things it still allows you in many ways to use your own way of doing it.
Since 2.x even more than ever before.
Once you understand what goes on behind the hood you start to like it even more. You are able to contribute to the framework code as well as the documentation directly.

My personal reasons to still stick with CakePHP

Well, first of all, after so many years working with it and contributing you kinda get attached to it. Within the last three years I rose to the one of most active core developers besides the master Mark Story πŸ™‚ After what one helped the framework to become it would not make too much sense to just hop on to the next framework without a good reason.
So here the hard facts:

Less coding time

CakePHP is all about reducing development time. So most of the things are already decided for you in best-practice approaches and you can overwrite only what you want to.
Using bake and other tools you have a usable app in no time. Adjustments in your code are then also just a couple of quick changes. Fast development means less costs and earlier results.

Fast core update/fix progress

Issues or enhancements usually get added pretty quick. From a few hours (happens quite often actually) to a few weeks. The less complicated the issue and the better your initial work the faster it gets approved and included. So providing a detailed report and a patch in form of a Github pull request can really speed up the process.


There are already quite a few very useful plugins or at least plugin-able snippets by very experienced programmers. You can easily use and enhance those.
I use my own plugins like Tools, Setup, … with various useful stuff to enhance the core and my apps even further in a DRY (Don’t Repeat Yourself) way.
That’s also one of the reasons why changing would be painful: I would miss so many of my already written Plugin classes I need every hour of every day. The overhead of rewriting it would probably be quite immense.

Busted myths

CakePHP is dead/legacy

Yeah, right πŸ™‚ That’s like super-lame to say. Check out the Github changelog and you will see how dead it really is.
Fact is, that with CakePHP3 the activity goes to a new all time high throughout the timeline. And that is just the beginning. Fact is also, that until now, it was a very constant log of activity and improvement.
Compared to other (very new) frameworks out there, that is quite the achievement. Most frameworks come and go as quick as the wind, but CakePHP is solid as a rock in
its presence and how it improves. People/Businesses can actually rely on it.

A far more interesting question would be: Why isn’t Cakephp popular despite being one of the earliest PHP framework to be written?.
People can get easily deceived by sparkling new "coolkidz" stuff. Backwords compatibility and reliability has’t been as important to any other framework. So they could progress to cutting edge in a faster pace, of course. There is a certain trade-off here to make. Nonetheless progress has been made, and that quite remarkable.
See for yourself.

CakePHP is slow

Yeah, that was partly true in 1.x due to missing lazyloading. So many things have been included without actually needing them. It could consume quite a lot of memory, as well. Since 2.x and lazyloading the developer is responsible for only fetching the data needed and making sure that caching and other speed/performance enhancements have been accounted for. Then Cake is not really that much slower than any other Framework or PHP script.
Sure: CakePHP 2 is still much more full-stack than most slim PHP frameworks. It might also not be cutting edge regarding speed. But with a little tweaking of server and app this difference is almost not measurable anymore.
And the upcoming version 3.0 beats even most other frameworks, as with composer autoloader dump and some minor caching layer it runs pretty darn fast. Even the routing, which often was a bottleneck, has been sped up a huge factor.

This is not even a good argument for comparison, as with server configuration this can easily be overcome anyway.
And what is often forgotten: CakePHP is actually super-fast in development time compensating for any speed issues compared to vanilla PHP coding.
If I had a project to finish, I would rather use CakePHP and 1/4 of the development time (and costs!) and invest those in better server infrastructure (fully compensating any speed issues and going beyond). The outcome: You still pay only half the costs πŸ˜‰

The documentation is outdated and incomplete

Total nonsense if you didn’t travel back in time. The documentation improved greatly since 2008 and Cake1.x. You could say that everything is covered and some things even more than you would probably need. Even the migration guides up until 2.6 (not released yet) are 100% complete and the code changed documented in the book in detail.
So if you don’t find something it must either be a really rare use case or you are not quite capable of using Google or the book internal search. Well, that is too harsh of course. We all overlook things sometimes. Drop in the IRC #cakephp channel and ask, if you really can’t find it, and you will be helped in seconds/minutes.

For CakePHP3.0 the focus was even put on documentation: Writing thorough docs for each part that has is been added in sync with the actual feature PR.
So far the result should be quite remarkable for a not-even-yet-RC version.

CakePHP is too much convention over configuration

I sometimes hear people complain about too many conventions and that you can’t configure CakePHP the way you like/need it. This actually was true in earlier versions.
But in 2.x this also improved quite a lot. You can pretty much configure/adjust the whole framework as you need it – either via extending, aliasing, replacing core files or events/callbacks.
Bear in mind that conventions are usually a good thing. They – in a default scenario – help you to get it done very quickly. If you start to reach an edge case you can still adjust accordingly, but first try to stay within the conventions for your own benefit.

With CakePHP3.0 this even goes one step further:
You can leverage the whole conventions stack if you want to, or you can go totally down your own path. The latter I wouldn’t recommend, though, as you really save a lot of config overhead when using conventions wisely.
Also: Using namespaces, there is pretty much no limitation anymore. Classes can be finally named the same without fatal errors. A simple use x as y and it’s resolved.
You can replace complete parts of the application. Since major parts like "bake" and "translation" are moved out of the core, you can also more easily extend and adjust those now.

My learnings

Over the years, you also learn from your previous work – and mistakes.
And we all make em. That’s natural.

Documenting is important

I didn’t really think of documenting in the beginning. Over the years there were many times were I had to regret that for various reasons.
So new plugins and functionality get documented from the start, making it transparent both for me and others what to expect.
I follow the approach to put the dochs directly into the repo as subfolder, containing a as overview. This is very handy (close to the code) and readable (automatic markdown parsing online).

Write tests

I also didn’t test much when I started to develop. Working with CakePHP showed me how simple and yet effective it can be to do that though.
You save yourself from a lot more regressions and it serves as part of implicit feature documentation, in case your forgot that.

Don’t reinvent the wheel

Yeah, back in 200x I had to write everything myself. But the systems around us evolve quicker and quicker. It is just impossible to keep up with everything and still write new application code. So if there are existing libs or services that do the job, I try to use them now. An example is "Carbon" for datetime or "Mailchimp/Mandrill" for sending emails/newsletters.

Keep code clean

Refactor once in a while to keep the code clean and readable. This makes understanding and extending it afterwards easier.
Follow best practice approaches where applicable. Use a documented coding standard and stick to it.

Learning from other code and frameworks

Other frameworks have different approaches, they are valid for some use cases nonetheless. I had to look into Symfony2 and alike for one or two projects and even if I wouldn’t use them for my RAD (Rapid Application Development) projects, they can be useful for other projects. I could also once in a while get some very good ideas from them on how to approach certain things, and sometimes even let them mold into CakePHP functionality.
Similar things can be said about existing library code out there. So be open minded and take a look over the "comfort zone" once in a while and suck in other people’s ideas and approaches.
And always check if the tools you use still are the right ones for the task. If at some point something could be better handled with a different framework, I would probably look into it. But knowing my "tool" quite well, I didn’t see anything yet that wouldn’t have been handled by it so far in an appropriate way for the tasks at hand.

Splitting Utility repos into smaller chunks

I wouldn’t exactly call this a mistake, it was more the logical choice back then with SVN (and later basic GIT). My Tools plugin got pretty loaded with stuff, just because it was easier to include a single plugin than trying to svn:externals or git submodules separate ones. The overhead was not acceptable.
Now in 2014+ with composer as de-facto standard, it looks a whole lot different. As such, I try to outsource some functionality of it into their own plugin repos, e.g. Geo and TinyAuth for 3.0. More should follow.

Which brings me to the last point which will also be easier with smaller repo code:

Follow some kind of semantic versioning

With composer this is an even more important task than before: SemVar is necessary to prevent incompatible libraries.
So if you develop new features for a plugin for one app, other apps using the old version should still function normally.
By always using a single branch directly, this can soon blow up. Using semantic versioning and releasing new versions (version numbers are cheap)
we can assert that everyone is happy and code breakage stays at a minimum.

What’s next

I will try to help with the release of 3.0, the next major step in PHP framework history, as much as possible besides my day job and extracurricular activities.
Earlier versions of CakePHP sure lacked the "coolness" of new PHP features, letting quite a few users drift off to other frameworks. I can understand that partially. We all want to use the newest and geeky stuff. If it is really necessary (at that point in time!) is a different story.
Anyway, CakePHP 3 will catapult itself to the very front, and probably beyond most other PHP frameworks. And rumor has it that this time it will try to stay on top – with a fairly high chance of succeeding.

So I am really looking forward to how this will change the balance of framework usage here again, and how probably many of laravel’s or symfony’s followers will jump back to the framework with the longest history of all. Stay tuned for more posts on how to prepare 2.x apps for 3.x so that the final migration will be as smooth as possible.

Don’t forget to spread the word about CakePHP(3). Blog, twitter, write plugins (or upgrade existing ones) …

Additional Resources

For German developers there’s a very recent podcast where I go into details about CakePHP.
The (English) one is mainly about upgrading between the different versions of the framework.

If you want to stay updated, subsribe to the blog RSS feed or follow my on twitter.

Merry Xmas everyone

And a great start into the next chapters of coding!

4.64 avg. rating (92% score) - 11 votes

Posted by Mark in CakePHP, PHP, WebDevelopment


CakePHP 3.0 coming up

03 Nov

CakePHP version 3.0 is coming closer and closer to a stable release.

The leap from PHP5.2 to PHP5.4 was more than necessary. Personally, I think, this will bring CakePHP back on the same level as "Laravel" or "Symfony2".
Those, using already PHP5.3 for a while, kind of left CakePHP behind. But now those will probably be overtaken again to some extend πŸ˜‰

Try it out now.

All you need is to clone the cakephp/app repo, run composer update on it and its ready to go.
Alternatively, you can run this simple command:

composer create-project -s dev cakephp/app [app_name]

Major differences compared to 2.x:

  • All namespaces. Note that they live only in the respective file. So try to avoid non-helper class usage in your view layer. Better to wrap them as helpers.
  • The former APP dir is now src, and a subfolder of the root dir. The composer.json file stays in root, though. So does "vendor" (note the lowercase v), "plugins", "tests", "config" and "webroot". So basically, the src now only contains the classes, view templates and Locale.
  • Directly uses PHPUnit – there is no shell and no web test runner anymore (I do miss the latter though sometimes – VisualPHPUnit is supposed to substitute).
  • Completely new ORM – returning objects to easily work with.
  • Session is not static anymore. So using it inside models/behaviors is discouraged.
  • Themes are now Basic Plugins.
  • Uses templates for FormHelper and CO – making it way more customizable.


If you followed my earlier posts you probably know by now that I paid close attention to the changes between 2.x and 3.x.
So my 2.x code already follows the new standards as close as it gets. This sure eases a possible 3.x upgrade.

The most important ones are:

  • Use composer and git (no git submodules etc)
  • Use query strings (remove all named params)
  • Remove deprecated functionality and provide shims if necessary

For details on latest 2.x upgrades see this article.

So use the following weeks or months wisely, and already bring your application to a current up-to-date version. Especially if you plan on upgrading it to 3.x some time.
Taking away already most of the work beforehand and in small and well testable steps is the best approach.

Even if you don’t plan to upgrade the outlined standards sure ease current and future development. And that saves time and money.

I will soon release a new post with some experiences of upgrading small 2.x apps to 3.x. So stay tuned.

First Cake3.x notes and tips

I have been playing around with the dev, alpha and beta release so far, and I like it a lot so far. A lot πŸ™‚

The migration guide looks intimidating for sure. But for new projects it will be irrelevant anyway.
I still would want to wait until at least a few important plugins are upgraded – so probably close to stable release.

How to overwrite static classes

This has been pretty much impossible to do without namespaces in 2.x so far.
Now you can overwrite/extend those classes very easily, as well. E.g. the Utility Hash class:

namespace App\Utility;
use Cake\Utility\Hash as BaseHash;
class Hash extends BaseHash {

You can then use App\Utility\Hash throughout your code to get access to any additional methods you want to add/change.

No need for phpunit composer dependency anymore

Use the phpunit.phar file directly and you don’t need the dependency in Cake3.x. It is also easier to work with, just drop it in your root folder and run:

php phpunit.phar

It will automatically read the config from the phpunit.xml file in your application’s root folder.

Oh, and CakePHP get’s more and more popular:

Currently it’s the 3rd most popular PHP framework on GitHub (No, codeigniter doesn’t count). For some reason ZF2 isn’t shown here. If you then compare RAD from CakePHP with the other two remaining ones, there really is only one to pick, isn’t there? After all, development speed matters…

3.67 avg. rating (76% score) - 3 votes

Posted by Mark in CakePHP


UTF8 can be tricky – especially with PHP

15 Aug

Everybody uses (or should!) UTF8 these days. An easy and fully supporting PHP version I did not come across yet, though.
It seems there is sometimes more to it. This article is supposed to guideline the basic setup of a CakePHP app using UTF8 and will go beyond that to the really tricky parts regarding the de facto standard encoding these days.

Note: this post is really long overdue and was in my draft folder for 2+ years. So here it is, quickly published before it got even more dusty^^
And dusty sure is the right word with (hopefully) no one using ANSI/ISO-8859-1 anymore these days.

UTF8 and PHP

Use the mb_ functions if you know that you real with strings than can contain UTF8 chars. So if you want to count the length of such a string:

$length = mb_strlen($string);

If you are simply manipulating strings, you do not always have to use those slower and UTF8-aware fnctions, though. But in doubt always do so.

UTF8 and preg_match()

Now this is a tricky one – especially if you don’t want to recompile PHP with the PCRE UTF-8 flag enabled or if you don’t know about it at all. IMO that should be the default, but it usually isn’t it seems.

Most times, when dealing with UTF8 strings, the /u modifier and p{L} helps:

preg_match('/^\p{L}[\p{L} _.-]+$/u', $username, $matches)

In other cases you might have to add (*UTF8) in your pattern.

UTF8 and CakePHP

CakePHP setup

The main parts are handled in the book, especially in the getting-started section.
But the main part that sometimes people get wrong is that the APP encoding is "utf-8" while in the database.php its spelled utf8.

Make sure you save all files as "UTF8 without BOM" via your IDE as soon as they start to contain UTF8 chars. Failing to do so will cause output issues.
I usually try to avoid this and use Locale translation and mainly English chars in all files as much as possible.

Note: Before adding any UTF8 chars to files, those files are always ANSI (there is no way without the BOM to distinguish those two encoding formats as they are one and the same here). So no matter how often you try to save them as UTF8, they will always still be ANSI. In case you wondered why it falls back to it again in most IDEs.

Correcting PHP functions

Some PHP functionality has been wrapped in CakePHP to overcome deficiencies regarding Unicode.
String::wordWrap() for example replaces the faulty wordwrap() function.

I also added a few fixes to my Tools plugin as Utility/Utility class:

  • pregMatch(): Unicode aware replacement for preg_match()
  • pregMatchAll(): Unicode aware replacement for preg_match_all()
  • strSplit(): Unicode aware replacement for str_split()
  • pregMatchAll(): Unicode aware replacement for preg_match_all()

Probably more to come..

Proper validation

Make sure your validation is unicode aware – that’s probably one of the most made mistakes from mainly English speaking devs/people.
They maybe assume that it works to simply use strlen() or a [a-z] regex or alike – not taking into account that for example many normal first/last names contain a lot of special chars.
Validation here should never be too strict. Otherwise a lot of people will be very upset.

So in the above example we do NOT want to use

preg_match('/^\[a-z][a-z .-]+$/i', $firstName)

but something more like

preg_match('/^\p{L}[\p{L} .-]+$/u', $firstName)

to validate a first name.
IF we actually have to validate this further than a simple "not empty" check is a different topic (I don’t think so). But if you really must, PLEASE do not shut people out because their parents gave them non-English names πŸ˜‰

A similar thing I had to fix in the core a while back, regarding domains/urls.
And this is CakePHP2.5 – the current master – so that topic sure is still quite current for some cases. More and more so with further internationalization.

Checklist for your CakePHP app

  • Ideally, use utf8_unicode_ci as collasion for your DB
  • Your layout should contain <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  • The apache/nginx should serve files as UTF8 via header Content-Type text/html; charset=UTF-8


Only in PHP7 (as PHP6 got skipped) there will be a more built-in approach then for UTF8. Until then (and maybe even then) we will have to fight quite a lot here for the next years.

There are even a few popular projects in GitHub around the UTF8 issues, e.g:


Might be worth checking out.

Anything missing? Please let me know.

4.00 avg. rating (81% score) - 4 votes

Posted by Mark in CakePHP


All new CakePHP Tips Summer 2014

05 Aug

For CakePHP2.x

Awesome CakePHP

Check out this all new awesome CakePHP list: awesome-cakephp
Star it, fork it, enhance it πŸ™‚

Note the cake3 branch that will proabably soon be filled rapidly with all new shiny CakePHP3 resources and plugins.

There are also a few more generic awesome lists links in there.

CakeFest 2014 coming up

Check it out – and be part of it. You can read about last year’s event here.

This year is going to be awesome (again that word^^). And not only regarding the temperatures in Madrid πŸ˜‰
A few well connected people like @philsturgeon pulled some strings and the event is listed on sites like
Let’s make this the largest fest ever.

Note: My attendance app only lists a very small subset of all people actually joining the event!

Finally a book on CakePHP2.5+

CakePHP Core Developer @josegonzalez wrote a cool book on CakePHP: Rapid Application Development with CakePHP 2.
It has some real insight in topics that are not covered by the online CakePHP documentation.

Hot tip: Use the promo code DEREUROMARK when purchasing the bundle to get 20% off your purchase!

Deployment with composer and script hooks

This is already widely used in Symfony2, for example.
Here it fires the following scripts after installing/updating to clear the cache and re-build assets etc:

"scripts" : {
	"post-install-cmd" : [

The list of available commands be found here:

Why not leveraging this for your Cake2.x app, as well?
You could re-built AssetCompress files, clear the persistent/model cache, run custom post-update hooks and so on. (DB) Migration could also be hooked in this way.

Post links inside Forms

Most probably didn’t see this change. But it allows postLink() to be used inside forms now.
The issue was, that forms don’t work inside forms. And that post links contain those inline, breaking the form around it.

You can now easily create "Delete" links or other POST links inside your forms. It can write the forms to a View block which you can output later on then.
All you need to do is set 'inline' => false:

echo $this->Form->postLink('Delete', array('action' => 'delete', 1), array('inline' => false));

And output your buffered View block after closing the form:

echo $this->View->fetch('postLink');

This also works with multiple postLink() calls. The View block would simply contain all of the forms then.

Prevent internal field names

I try to stay away from internal framework used names for fields. Once you attach Search plugin or any other additional functionality on top of your
actions, this could get messy otherwise.
The Paginator, for instance, uses "limit", "sort", "direction", "page". In order for them to not conflict with search fields on existing fields, I avoid them and
use "order" instead of "sort" or "max" instead of "limit" for field names. In case this is not avoidable or a legacy DB schema, one can add the model prefix, though: "MyModelName.sort" and would also be able to resolve the conflict. But if you can already do so in hindsight it is probably smarter.

Array and ArrayObject

The new CakePHP3 core uses ArrayObject already quite a bit.
In 2.x you probably don’t use it too much yet. But it is wise to voice a warning regarding on some flaws of ArrayObject.
This article describes it.
Basically, empty() and ArrayObject don’t play nice. It only works with count():

if (count($options)) {
	// Yes
} else {
	// No / empty

The alternative would be to cast it prior to checking on it: (array)$options. Then empty() would work again.

The same issue you might face in index views and alike, where you want to display a subsitute text if no records can be listed in the pagination yet:

if (empty($users) { // BAD - better use count() here then.
    echo 'No users enlisted so far';

This would also always fail now in CakePHP 3 without any indication whatsoever as objects replaced the arrays and render empty() invalid as check here.

The rest of those issues in the article are also quite interesting. Check them out, as well.

A complete list of "flaws" has been put together on this page. It reads like the bible of Anti-PHP, tough πŸ™‚
Quite entertaining even in some parts. I would just read it as an informative page, though. It is good to know those things, but it is also easy to avoid or work-around them.

MySQL and returning integers

Some probably wondered why integers and other non-stringish values is often returned as string.
This has nothing to do with CakePHP itself, but with the PDO extension of PHP underneath.

But you can easily disable that with the following flags in your database.php config:

'flags' => array(

UUIDs as char36 vs binary16

UUIDs (Universally Unique Identifier) can be used as an alternative to the normal AutoIncrement IDs for primary keys. Use them wisely, they are larger and slower than than the AIIDs.
But if you use them, try to prevent char36.
According to tests such as storing-billions-uuid-fields-mysql-innodb, it is 6-8 times faster to use binary(16) instead of char(36) for UUIDs.
CakePHP 2.x+ supports binary just fine.

PHPUnit and Windows

You might have seen something as descibed in this issue: Weird output in your console when running unit tests.
This is mainly because the default setting for PHPUnit in the phpunit.xml(.dist) file is usually colors="true".
You can easily overwrite it in your own file and the weird output stops:


Or you can try to use the library linked in that ticket. I didn’t try that one yet.

0.00 avg. rating (0% score) - 0 votes
No Comments

Posted by Mark in CakePHP