While CakePHP 2.4 is now just around the corner (already beta), a few tips gathered the last few days.

Don’t mix controller and component pagination

Currently, if you mix controller pagination setup and call the Pagination component then, it can easily backfire as the two different
settings are not always merged as you would expect it to. So don’t mix em.

My recommendation: Stick to controller pagination for now (as we all have the last years) as it seems it won’t be deprecated after all. It is a nice
convenience access to the component anyway.

PS: If sticking to controller pagination, add this rejected PR snippet to your AppController to avoid the notice thrown.

Test your code

Even if you don’t assert the outcome.

"But that is time consuming. I dont have time!"

Yeah, sometimes you are in a hurry and can’t properly assert all tests. Still no excuse.
Just be running the code via "dummy call" and having the test not through any notices/warnings/errors you already have a very basic level of testing. And it really doesn’t need time to set such a basic test run up.
As soon as there is time you can then still address the proper result. But until then you at least know that no line of code is suddenly gone missing or variables have
accidentally been renamed etc.
Such a basic "run-through" test is still better than no test at all:

When testing actions that contain redirect() and other code following the redirect it is generally a good idea to return when redirecting. The reason for this, is that redirect() is mocked in testing, and does not exit like normal. And instead of your code exiting, it will continue to run code following the redirect.

Even if for your productive environment the return will be superfluous, the test cases will not return wrong results.

I just recently adjusted my bake templates and it has also been changed in the 2.4 branch of the Cake core. I advice you to update your files, as well. You can use my Upgrade shell task "controllers" to do that as a batch job for your app and plugins:

Debug SQL queries by throwing exceptions

Ever worked on an ajax, csv or even a redirect action where there will be no debug SQL bar at the bottom etc?
You can easily display your SQL queries up to a specific point by throwing an exception:

$someRecord = $this->Model->find(...);
// We just add this snippet here to halt and see the actual SQL query before we continue:
throw new Exception();
if (!$someRecord) {
return $this->redirect(...);
}
return $this->redirect(...);

This halts the code, shows the error layout with all the queries listed below. Neat, isn’t it? And it is quite fast and works anywhere in your application.

Switch from constants to a more flexible way of configuration

In our case we can leverage the Configure class and its read() and write() methods to do so. Better than constants anyway as they can only be defined once and not changed anymore.
So it’s only reasonable that the 2.4 core deprecated quite a few of those constants like FULL_BASE_URL, DEFAULT LANGUAGE, CAKE_SHELL etc.
Using Configure we can store a default value and overwrite it any time after that with a different value if we need/want to.

In the past I also caught myself using constants where Configure would have sufficed. Partly to make myself believe my app will be faster this way.
The speed advantage is so minimal though that it does not outweigh the reduced flexibility that comes with it.

So instead of using define('FULL_BASE_URL', 'http://example.com') you can now use Configure::write('App.fullBaseURL', 'http://example.com'); and overwrite it again later on.

Same goes for any settings you might want to set. Chose a meaningful namespace to group them, though:

Change your default validation error message

It will be changed in 3.x from "This field cannot be left empty" to "The provided value is invalid".
This makes sense as in most cases it would display this error message when a value is provided but does not pass the specific validation rule (like numeric or email).
This is highly confusing then.

'email' => array(
'notEmpty' => array(
'rule' => array('email')))

This example would just fallback to "This field cannot be left empty" here – both on empty submit and if you input some invalid email.

So you should already address that in 2.x by always defining the error message for your rules with the above wording. Clearer validation error messages will help your users to correct their mistakes and submit the form properly. Only use "This field cannot be left empty" for actual "notEmpty" cases then:

Also try to use the verbose array declaration and don’t forget 'last' => true for consecutive validation rules (as in postal_code above).

Text(area) to paragraphs

Use the new Cake2.4 method TextHelper::autoParagraph() to display your textarea input. It will automatically format single line breaks to <br /> and double ones to <p> blocks.
If you are still on 2.3, you can copy this method over into a TextExt helper, for example, and use aliasing to map it back to "Text" helper alias. When upgrading you won’t have to change your code then a bit 🙂

Important: Do not forget that this method does not escape your output. Thus you need to use h() for (potentially unsafe) user input:

echo $this->Text->autoParagraph(h($text));

h() will effectively remove any XSS dangers as well as defuse any HTML chars like < or > that could otherwise destroy the layout (but are totally valid chars for quoting in some languages).

Check if you need the hardcoding of your core lib path

By default CakePHP "bake project" for new apps will hardcode the paths in your index.php and test.php – if you don’t have CakePHP in your include_path. Which most don’t, especially when maintaining multiple different Cake versions and apps.
So you might want to (I do anyway) comment those lines out again after baking the project:

You will stumple upon that when deploying your scripts. So better take care of it asap.

Check out the 2.4 core

While it is still beta, you can test it already, though. I even use it for new apps (Disclaimer: don’t do that if you are new to CakePHP!).
You can test the new features or how your 2.3 app would run with it. You can realize quite early this way where potential pitfalls are.
In the past I often discovered some "bugs" this way that then could easily be fixed or adjusted before your code actually some day depends on it.
While still in beta you might also be able to add some additions to new features before you will have to wait for 2.5 again or something.
So it’s worth to at least play around with it now.

Also keep an eye on the 2.4 migration guide and maybe even 3.x migration guide as well as 3.x chatter and how your code would be affected or would have to be modified. It might save you some time in the upgrade process if you can already eliminate some of the necessary changes in advance.

One example for 3.x, that is not yet officially mentioned yet, is the possible deprecation and removal of Model::read(). It is a method I have always been preaching to avoid. Especially if you are a beginner, but also if you can (and you always do) use find() instead. The cookbook now also states this in a warning.

I never used it once and it seems that there is very high possibility that it will be removed in 3.x. So if you catch yourself using it today, think about this and if you might be able to replace it with the find() wrapper from here on 🙂 To be on the safe side.

The autoRedirect automatically redirects back to the site the user came from if possible (if the user clicked a link). Otherwise it will use the provided fallback url.
The postRedirect is a wrapper for the future where one day 303 can be used without causing trouble (read further for details).

prgRedirect

Why is this necessary in some forms? Most search forms do a simply post. What they should do is a POST + GET afterwards. Thats called PRG pattern and is described here.
Especially after posting search forms or entering data you want to avoid a nasty message like some modern browsers produce if you then hit the back button. You want to graciously display the page prior to the post. Thats where this extra redirect comes into play. Always redirect after a post – quite easy to remember.

if (!empty($this->data)) {
if ($this->Model->search($this->data)) {
# save POST search to session, redirect and display the search result as GET
$this->Common->prgRedirect();
}
}
if ($search = $this->Session->read(...)) {
...
}

As the comment in the method head as well as other sources explain one should NOT use 303 or you end up with broken forms for some users.

Note the failsafe with the cookie. If cookies are disabled this would result in empty sessions and therefore never work. For disabled cookies there cannot be a redirect and therefore needs the POST to display the data.
Therefore your forms should work with both POST and GET for this very same reason. The "prg" redirect is only an enhancement to provide better functionality in the normal use case (where users do use the back button).

Moved/deleted content

If you moved or deleted some content you can use the 301 redirect to tell search engines and browsers where to find the same content at the new location or where to go to instead:

The Problem

"When you have two different addresses pointing to the same page, like www.example.com/offers.html and example.com/offers.html, many search engines (or so we are led to believe) will treat those two URLs as two separate pages. When you, as a human, see those two pages and notice they are identical, you will automatically realise (correctly) that they are actually the same page. Apparently, the search engines do not make this assumption, and will regard those as different pages with duplicate content."
(source: www.thesitewizard.com)

I personally think that apart from the SEO problem there shouldn’t be two different urls to the same content in the first place.

So what do we do?

The bad thing to do would be to disable one of the domains (root or www).
We want to select one (www.example.com) as default domain and if someone just enters "example.com" he will be automatically redirected to our default domain.
Again – the bad thing would be to use meta redirects. We want to use so called permanent redirects ( code 301) in order to notify search engines and browsers about the reason we want to redirect.

Using Mod Rewrite

For the cake app to be available per "www.example.com" (and a 301 redirect from mydomain.de) you just need to modify the htaccess file in the /app/webroot/ folder:

The "localhost" part is not necessary – but it prevents your local htaccess file to redirect on your development computer. That is if you have your htaccess file in svn or git and therefore both versions (local and stage) are the same.

The reason why i did not lay out the other direction (www to root) is simple: I don’t think this makes sense. Most people not so comfortable with the internet usually type the complete address anyway – they just expect a "www" in front of the domain for the main website.
And with the internet getting more and more complex, some guidelines should just remain. One is that you don’t use root domains for websites. (I could go into details here – about other side effects like "technical" cookie problems occuring with root domain sites etc – but i will leave that out for now)

Using Apache Directives

This is way faster because the server doesn’t have to open the htaccess files for it. It can directly use what it has to have available anyway.

Inside /etc/apache2/sites-available/ there should be your domain file.
Between <Directory> and </Directory> you can add the above lines.
To actually increase the performance we now need to disable htaccess files for this domain.
Add AllowOverride None directly above your new lines. This prevents the server from looking for, opening and processing htaccess files.