Monday, September 18, 2006

21 Things You Must Know About CakePHP

Original >>

Easily creating static pages

I needed to create several pages that didn't use any models and contained static data inside the default layout. My first thought was to create a controller for these pages and define an action for each static page I needed. However, this solution seemed tedious and would make it difficult to quickly add new pages. Enter the pages controller - simply create a view inside the views/pages/ folder and it'll automatically be rendered in /pages. For example, if I created /views/pages/matt.thtml it would be accessible via http://www.example.com/pages/matt

Static pages - Adjusting the page title

If you're using the pages controller and you need to change the page title, add the following to your view:
<? $this->pageTitle = 'Title of your page.'; ?>

Static pages - Adjusting other data sent to the layout

If you need to send data to the layout (such as a variable indicating what section to highlight on the nav bar), add this to your view:

<? $this->_viewVars['somedata'] = array('some','data'); ?>

That array should then be accessible as $somedata inside your layout.

Creating a simple admin center

If you need to create an administrative back-end for your CakePHP site and would like all the actions with administrative capabilities to exist under a specific folder, open up config/core.php and uncomment:
define('CAKE_ADMIN', 'admin');
This will then make all actions that are prefixed with "admin_" to be accessible via:
/admin/yourcontroller/youraction. For instance, if I created an action in my posts controller called "admin_add," I would access this via: www.example.com/admin/posts/add
From there I could simply password the admin folder to prohibit unwanted users from adding posts.

Viewing the SQL queries that are running behind the scenes

You can easily see the SQL queries that CakePHP is running by adjusting the DEBUG constant in config/core.php. 0 is production, 1 is development, 2 is full debug with SQL, and 3 is full debug with SQL and dump of the current object. I typically have debug set at 2, which renders a table at the bottom of the page that contains SQL debug information.
If rendering a table at the bottom of your site is constantly breaking your layout during development (especially if you're making AJAX calls and you're getting SQL inside your pages, not just the bottom), you can easily style this table to be hidden by adding this to your CSS:
.cakeSqlLog { display: none; }
This will allow you to view debug information in the HTML source code without your layout getting mangled, just don't forget to set debug back to 0 when your site goes live.

Multiple sources of documentation

Don't just rely on the manual. The wiki and the API are invaluable sources of information. The tutorials in the wiki are especially useful, and the API may be daunting at first, but you'll quickly find the information in there is crucial to building a site with CakePHP.

Using bake.php

Bake is a command line PHP script that will automagically generate a model, controller, and views based on the design of your database. I highly recommend using scaffolding to get a prototype going of a table that may change a lot in the beginning. If you're fairly certain the data is not subject to any drastic change, I recommend using bake instead. With bake all the files are generated and written to disk and you can make modifications from there. It saves a lot of time doing the repetitive tasks such as creating associations, views, and the basic CRUD controller operations.
Using bake is really easy. Once you have a table(s) in your database created, change directories to the /cake/scripts/ folder and run:
php bake.php
If you choose to bake interactively it'll walk you through the steps required to create your model, controller, and views. Once everything has been baked I usually go through all the generated code and make custom modifications as needed.

Mind permissions when moving cake around

When I changed from the development server to the live server I tarred up my entire cake directory and scp'd it to the new server. Immediately I started having an issue where any time the debug level was set to 0 (production mode), data would not be returned for certain database calls. This was a bit of a catch 22 since I needed to view debug information to troubleshoot the problem.
Someone in #cakephp kindly pointed out that permissions on the /app/tmp folder need to be writeable by apache. I changed the permissions to 777 and the issue went away.

Complex model validation

I needed to validate beyond just checking to make sure a field wasn't empty or it matched a regular expression. In particular, I needed a way to verify that the email address users registered with was unique. In the wiki I found this gem: this advanced validation tutorial, which covers some advanced methods of validation that were very useful.

Logging errors

$this->log('Something broke');
This will log your error to /tmp/logs/ (I initially made the mistake of thinking it would log it to the apache error log)

Creating a controller that uses other models

Suppose you have a controller that needs data from a bunch of different models, simply add this to the top of your controller:
class yourController extends AppController
{
var $uses = array('Post','User');
}

This controller would then have access to both the Post and the User model.

Creating a model for a table that doesn't actually exist in the database

I needed a way to create a model and controller without actually having an associated table in the database. I particularly wanted to make use of the $validate array so I could easily validate my fields and keep the validation logic in the model. CakePHP will throw an error if you create a model for a table that doesn't exist. Adding this to the model fixed the problem:
var $useTable = false;
You can use this to change tables names as well.
var $useTable = 'some_table';

Call exit() after redirecting

This should be no surprise to anyone who has done any serious web development in the past, but make sure you call exit() after running $this->redirect() if there's code afterward that you don't want to run. I've always done this in the past, but I made the assumption that $this->redirect() would make an exit call for me (which it didn't).

Advanced model functions

Unless you delve in to the API, there are some very useful model functions at your disposal you might not know exist. I highly recommend reading over the Model Class Reference at least once. Here's a few key functions I wasn't aware of that I found to be very useful:

  • generateList() - I use this function primarily to populate select boxes with data from associated tables
  • findBySql() - Sometimes you just need to write your own SQL
  • findCount() - Returns number of rows matching given SQL condition
  • hasAny() - Returns true if a record that meets the given conditions exists.

Again, I highly recommend reading over the entire model class reference, you'll be surprised at what you learn.

Inserting multiple rows in succession

I had a situation where I needed to iterate through a list of items and insert new rows for each. I quickly discovered that if you insert an item and then immediately insert another, the item that is inserted next doesn't insert at all. Instead the previously inserted row was being updated. For example:
$items = array('Item 1','Item 2','Item 3');
foreach ($items as $item) {
  $this->Post->save(array('Post' => array('title' => $item)));
}

This code will result in a single entry in the posts table: "item 3." CakePHP inserted "item 1", but then updates it to become "item 2," then "item 3" because $this->Post->id gets the value of the last inserted ID. Normally this functionality is very useful, but in this particular instance it was not. I found was to setting $this->Post->id = false after each insert solved the problem.

Inserting logic before or after controller functions

Suppose you needed an array of colors to be available to every view rendered by your controller but you don't want to have to define this data in every action. Using the beforeRender() callback will allow you to do this:
function beforeRender() {
  $this->set('colors',array('red','blue','green');
}

This would make $colors accessible in every view rendered by that controller. beforeRender() is called after the controller logic and just before a view is rendered.
There's also beforeFilter() and afterFilter(), which are called before and after every controller action. For more information, read up on callbacks in the models section of the manual.

Adding a WYSIWYG editor to CakePHP

I found this great tutorial on getting TinyMCE set up with CakePHP. Basically you just link the tiny_mce .js file to your page and then add a small bit of init code to every page that you want textareas to be converted into TinyMCE editors.

Writing your own SQL for HABTM relationships

I had an issue with trying to create a HABTM (has-and-belongs-to-many) relationship where I needed to specify my own SQL statement. According to the docs (at the time of this writing) you should set finderSql in your model, but according to the cakePHP source you should set finderQuery instead. It's just a foul-up in the docs, but I figured it'd be worth noting to save others from having to figure it out for themselves. Trac ticket here: https://trac.cakephp.org/ticket/1217

Sending email

I found two tutorials in the wiki: Sending email and Sending email with PHPMailer
I highly recommend the latter of the two, sending emails with PHPMailer is more secure and there's less of a headache because you don't have to deal with constructing the mail headers yourself.

Customizing HTML generated by the Helper

I needed to change the default <option> generated when I called $html->selectTag() to say something like "Please Select" rather than an empty space (default). I also wanted radio buttons to have labels so the user doesn't have to click exactly on the radio button itself but can instead click anywhere on the text associated with it.
Create the file /app/config/tags.ini.php and add the following:
; Tag template for a input type='radio' tag.
radio = "<input type="radio" name="data[%s][%s]" id="%s" %s /><label for="%3$s">%s</label>"
; Tag template for an empty select option tag.
selectempty = "<option value="" %s>-- Please Select --</option>"

You can get a full list of available tags in /cake/config/tags.ini.php. I wouldn't recommend modifying that file, however, because you could lose your changes when you upgrade CakePHP.

Creating a custom 404 error page

If you need to change the page that users see when a document is not found, create:
/app/views/errors/error404.thtml

48 Comments:

Blogger Fraggle said...

Excellent!
Thank you

2:23 AM  
Blogger gaara - kun said...

i think it is very difficult to understand about cahe-php because several time ago i ever try to understand about this framework, i try to ask in mirc and the last is i'am give up and try to get build my own website without any framework. couse some time i very confused it is very important to know about framework...please teach me more...thankz

4:52 AM  
Blogger Huggie said...

All very useful info, thanks for the tips!

12:13 AM  
Blogger Sarah said...

Great list, I've added it to delicious. A few things there I hadn't taken the time to nut out yet, so you saved me some time.

That custom find sql thing will be useful. I've got one application that goes nuts because the child records are so huge.

12:39 AM  
Blogger adouglass said...

per ... Viewing the SQL queries that are running behind the scenes

The line

.cakeSqlLog { display: none; }

should actually be

#cakeSqlLog { display: none; }

1:04 PM  
Blogger anta said...

Good tips buddy :)

10:52 PM  
Blogger Dustin Weber said...

Helpful tips. Thanks for sharing.. a few in particular saved me some time.

- Dustin Weber
http://www.dustinweber.com

11:11 AM  
Blogger han said...

it's very useful for me,thanks very much
thanks for your generous sharing

8:53 AM  
Blogger yeastinflexion said...

moving cake tip: make sure your ftp client bothers with empty folders.

4:52 PM  
Blogger Octopus said...

Can I get some sample cakephp application with pagination component? how to implementation pagination component? :(, I've tried to used it but not success, help me please :(

2:10 PM  
Blogger himanshu said...

Hi i m a beginer in cake frame work ,while creation a blog page i was not able to redirect the page from index page,can you help me in this regards its urgent

4:26 AM  
Blogger cbmeeks said...

Very nice list.

Thanks

http://www.signaldev.com

12:01 PM  
Blogger Ara said...

Thanks for the info on "Inserting multiple rows in succession"... you really saved my butt!

10:29 PM  
Blogger Navi said...

great tips. As a newbie to Cake and a Rails lover, I found this very helpful to develop my first site in cake. Thank you!

3:00 AM  
Blogger Wilhelm Raab said...

'bout the "insert multiple rows" - I've encountered the same problem and solved it basically the way you did. However, today I found the function "create()", and I figure (but havn't checked yet) that it does for you what we've been forced to do the 'ugly' way.

11:24 AM  
Blogger Cavite Homes said...

Neat! I'll make most of these in practice.

Actually 1 tip to add in your list:

/views/layout/*.thtml aren't always have to start in html tag. To produce an xml output specially if you're doing AJAX you can do this:

/** xml.thtml
use it with
$this->layout = 'xml'; */
<?php
header("Content-type: text/xml");
echo \'<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\';
?>
<?=$content_for_layout?>


- Frederick -
http://www.phpmanila.com

1:42 AM  
Blogger Fields said...

Thanks for all the useful information .. Cake is great but is lacking in tips and tricks such as those you wrote.

Thanks

3:25 PM  
Blogger Philip, the Equal Opportunity Cynic said...

This is a wonderful resource! Thanks.

However, apparently cakephp.org discontinued the wiki without preserving existing links to the content, so all those links are now dead. Some of that might be in the bakery. I certainly hope so, because the scaffolding tutorial would be extremely useful to me.

8:44 AM  
Blogger Tiago said...

This comment has been removed by the author.

6:09 AM  
Blogger Gaurav_M said...

This comment has been removed by the author.

4:32 AM  
Blogger Gaurav_M said...

Great one for noob like me

Thanks a lot

4:33 AM  
Blogger Bunk said...

This is the key to Cake's cryptic manual!

Great work, I am no longer fumbliiiiing in the dark.

2:38 PM  
Blogger Andrew said...

Great post, thank you! The static pages info was what I needed most, but the rest are gems.

6:38 AM  
Blogger [.::MDT::.] said...

Please update some links, the cakephp wiki seems offline.
Thank you for this useful list, bye!

2:50 PM  
Blogger Mike said...

Great post, it's been a lot of help while I've been learning Cake.

Unfortunately someone has stolen most of this content and reposted it (word-for-word) as their own:

www.[BROKEN_HERE]blognol.[NO_GOOGLE_JUICE]com/cakephp-development-tips

2:50 PM  
Blogger Simons private Blog said...

Found this via Google. Incredibly useful.

10:41 AM  
Blogger Azo said...

Just want to add, for CakePHP 1.2 the Bake is now in cake/console directory. Type "cake bake" and follow the instruction.

1:30 AM  
Blogger onest group said...

Your Tips are very useful. Thanks a lot. Whenever i m trying implement some tips are not working such as static page show that not belongs any controller and other one is #cakeSqlLog { display: none; } don't show any query on innter view page.

5:04 AM  
Blogger Dustin Woodard said...

Oh my Goodness... Thanks

php cake.php bake

nowhere else did I see how to do that... thanks

12:24 AM  
Blogger Primate said...

Thanks for the help!

In 1.2, though, you don't need to use $this->_viewVars to send data to the layout. Just use $this->set("variable", "content") from your view, and it'll be accessible from $variable in the layout!

6:20 AM  
Blogger Miguel said...

Very useful, very thoughtful, very good!!!

Thanks

6:03 PM  
Blogger bawo said...

i have a site with a panel available in all pages. How can i set content to this default panel ? for example: i have a news website. My right panel is 5 newest new. When i go to anywhere in my site, 5 newest new always available for me in right panel of any page. THanks for answering me :)

11:36 AM  
Blogger Elvin Haci said...

Very useful i think, thanks

1:04 AM  
Blogger jpablobr said...

Hi,

I create the /app/views/errors/error404.thtml

But it's not working... is there something else I should do?

Thanks! great tips!

3:58 AM  
Blogger natebean said...

Very helpful, this makes cakePHP look even better.

Thanks.

6:36 PM  
Blogger Ariel said...

in the most recent version of cake, it's error404.ctp

3:35 PM  
Blogger a.group.of.friends said...

Nice article. Cake's API started using cake like URLs and broke one of your links, however. Find
http://api.cakephp.org/class_model
and replace it with
http://api.cakephp.org/class/model

~Dustin

4:16 PM  
Blogger Randdot said...

You can also easily add pages to the Webroot folder, you can add anything there and then call them as any static page.

11:46 AM  
Blogger Adrenalin said...

"Call exit() after redirecting"

In fact I think you don't need to do that as cakephp by default is doing exit().

Looking in the code,

cake/libs/controller/controller.php
536: function redirect($url, $status = null, $exit = true) {
...
632: if ($exit) {
633: $this->_stop();
633: }

And the _stop() basically is doing exit

cake/libs/object.php
139: function _stop($status = 0) {
140: exit($status);
141: }

So unless you call redirect with the 3th pram false, redirect will halt the script, so you don't need to call exit() after.

Otherwise your list is great !

1:20 AM  
Blogger Ankit said...

CakePHP is a free, open-source, rapid development framework for PHP. It's a foundational structure for programmers to create web applications. Our primary goal is to enable you to work in a structured and rapid manner without loss of flexibility.

CakePHP takes the monotony out of web development. We provide you with all the tools you need to get started coding what you really need to get done: the logic specific to your application. Instead of reinventing the wheel every time you sit down to a new project, check out a copy of CakePHP and get started with the real guts of your application.

CakePHP has an active developer team and community, bringing great value to the project. In addition to keeping you from wheel-reinventing, using CakePHP means your application's core is well tested and is being constantly improved.

View Cake Tutorial

5:09 AM  
Blogger Robin Thomas said...

Great Article on Cakephp dude... I was looking for something else and found this useful tips.. just bookmarked it. Some links(tinymce) are broken in ur article.Please update it.. Thanx a lot.
Robin Thomas

6:36 AM  
Blogger sandesh2782 said...

How can use my custom css instead cake.generic css in a web page?

I want a simple login page where user can be authenticated from a database table and I should be able to a user session.

Can anyone give me some guidelines in this regard?

7:43 AM  
Blogger sYzYgY said...

really useful tips !!.. thanks a lot.

1:08 PM  
Blogger MSS said...

i have problems:
Cake is NOT able to connect to the database.

6:28 PM  
Blogger ronin1770 said...

The The Cheap Web Hosting is one stop for the comparison of best web hosting solutions providers. Easy-to-Understand Comparison Grid allows to quickly identify list of features offered by major Web Hosting Providers.

Compare Hosting Plans for:

1. Basic Hosting
2. Budget Hosting
3. VPS Hosting
4. Dedicated Hosting

Don't forget to review ours Hot Promotions sections for discount coupons and deals on Web Hosting Solutions

2:53 AM  
Blogger Mikk said...

to jpablobr:
check cake/libs/controller/controller.php and change
var $ext = '.ctp';
to
var $ext = '.thtml';
or whatever you like

1:36 PM  
Blogger Nehal said...

Inserting multiple rows in succession

rather the resetting Id of the Post model use the create() method in iteration.


foreach($items as $item)
{
$this->Post->create();
$this->data['item'] = $item['name];
$this->Post->save($this->data);
}

3:14 AM  
Blogger .netobfuscator said...

It is really good but don't you think that it is not understandable by the beginner.

.net Obfuscators

4:51 AM  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home