All new CakePHP Tips and Tricks

This is supposed to be a list of useful tricks gathered over many months.

First Templates, then Bake, then Adjustments

The usual workflow for a new project should be

This way you speed up your development while having all the advantages of custom templates.
Follow the link to read more about the topic.

Don’t sanitize

Sanitizing is not always bad (see later on). But most of the times we don’t have to sanitize every bit of input.
Its overhead and usually makes more harm then good.
On save to database nothing is needed as Cake properly escapes data itself.
What we DO need is some protection in the view.
Use h($var) in the views to make sure all potential dangerous strings are now harmless. This is called "escaping".
Note: You would have to do this with any string that gets in contact with the user. So if you use database content in flash messages, you would have to escape before you call setFlash() – or escape the content in the session flash element (but if you want to be able to use HTML output, the second option is not going to work). Alternatively you could use BBCode for flash messages. That would allow you to use h() and any HTML markup together.
To sum it up: Try to be less restrictive on the input but still make sure your site is safe. This makes the user happier and keeps the efforts for security as low as possible but as high as necessary.

BAD Example:
Firstname/Lastname input fields validated with regexp or [A-Za-zäöüÄÖÜß]
We can see that all major German signs are accepted. But what if a French guy wants to sign up. His name might be Aimé. He would be quite frustrated with the website and leave!

GOOD Example:
Simply validate the length and escape the name on output. Every possible name is accepted 🙂

echo h($user['User']['first_name']);

So follow these tips and you will be fine!

Careful with the super-automatic methods

Methods like updateAll() and deleteAll() are a little bit different from the normal save() or find() methods.
They accept expressions and therefore don’t automatically escape the content. You should only use them with own "controlled" input or after sanitizing the data thoroughly. Otherwise your SQL queries might break or can even be used in harmful ways against you and your site.

Those methods like updateAll() can be pretty handy or even necessary if you need atomic DB updates.
Example:

$this->Model->updateAll(array('Post.view_count' => 'Post.view_count + 1'), array('Post.id' => $post['Post']['id']));

Even if two users trigger this the exact same moment, it will raise the count twice. If you use find() and saveField() you might end up overriding each other and raising it only once.
But in this example the input is not from the user and can therefore be considered safe.

If you use user-input you should cast (string to int if applicable) or strictly sanitize to assert that sql injections are not possible!

Working with dates

I created some date constants in my bootstrap:

define('DEFAULT_DATE', '0000-00-00');
define('DEFAULT_TIME', '00:00:00');
define('FORMAT_DB_DATE','Y-m-d');
define('FORMAT_DB_TIME','H:i:s');
define('FORMAT_DB_DATETIME', FORMAT_DB_DATE . ' ' . FORMAT_DB_TIME);

// now I can use it everywhere (controller, models, views, ...)
$today = date(FORMAT_DB_DATE);
$yesterday = date(FORMAT_DB_DATE, time()-DAY);
$exactlySevenDaysAgo = date(FORMAT_DB_DATETIME, time()-7*DAY);

A very clean and readable approach.

Always try to use the SECOND, HOUR, DAY .. constants.
Note: Everything above WEEK gets fuzzy (MONTH is always 30 days). So for everything from MONTH up you should use the PHP5 DateTime object to correctly add months/years.

Using debug mode 1

Right now you can usually switch between debug mode 0 (no debug) and 2 (3 is not used anymore). With debug mode 2 you usually display the debug bar or debug plugin etc containing the SQL queries and other stuff.
My idea quite some time ago: Why not using 1 as well? 1 could mean debug output is on but no debug bar is displayed. It simply triggers all debug warnings/errors.
Simply make sure that your debug level is > 1 at the bottom of your layout:

$debug = (int)Configure::read('debug');
if ($debug > 1 && Configure::read('Debug.helper')) {
    // display debug tabs with SQL queries etc
}

For debug 1 it will still display all debug messages. And with debug 0 it is still debug-free.

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.