Create a Quick Application in CakePHP: Part 1

Ahsanul Bari

September 2009

The ingredients are fresh, sliced up, and in place. The oven is switched on, heated, and burning red. It is time for us to put on the cooking hat, and start making some delicious cake recipes. So, are you ready, baker?

In this article, we are going to develop a small application that we'll call the "CakeTooDoo". It will be a simple to-do-list application, which will keep record of the things that we need to do. A shopping list, chapters to study for an exam, list of people you hate, and list of girls you had a crush on are all examples of lists. CakeTooDoo will allow us to keep an updated list. We will be able to view all the tasks, add new tasks, and tick the tasks that are done and much more. Here's another example of a to-do list, things that we are going to cover in this article:

  • Make sure Cake is properly installed for CakeTooDoo
  • Understand the features of CakeTooDoo
  • Create and configure the CakeTooDoo database
  • Write our first Cake model
  • Write our first Cake controller
  • Build a list that shows all the tasks in CakeTooDoo
  • Create a form to add new tasks to CakeTooDoo
  • Create another form to edit tasks in the to-do list
  • Have a data validation rule to make sure users do not enter empty task title
  • Add functionality to delete a task from the list
  • Make separate lists for completed and pending Tasks
  • Make the creation and modification time of a task look nicer
  • Create a homepage for CakeTooDoo

Making Sure the Oven is Ready

Before we start with CakeTooDoo, let's make sure that our oven is ready. But just to make sure that we do not run into any problem later, here is a check list of things that should already be in place:

  1. Apache is properly installed and running in the local machine.
  2. MySQL database server is installed and running in the local machine.
  3. PHP, version 4.3.2 or higher, is installed and working with Apache.
  4. The latest 1.2 version of CakePHP is being used.
  5. Apache mod_rewrite module is switched on.
  6. AllowOverride is set to all for the web root directory in the Apache configuration file httpd.conf.
  7. CakePHP is extracted and placed in the web root directory of Apache.
  8. Apache has write access for the tmp directory of CakePHP.

In this case, we are going to rename the Cake directory to it CakeTooDoo.

CakeTooDoo: a Simple To-do List Application

As we already know, CakeTooDoo will be a simple to-do list. The list will consist of many tasks that we want to do. Each task will consist of a title and a status. The title will indicate the thing that we need to do, and the status will keep record of whether the task has been completed or not. Along with the title and the status, each task will also record the time when the task has been created and last modified.

Using CakeTooDoo, we will be able to add new tasks, change the status of a task, delete a task, and view all the tasks. Specifically, CakeTooDoo will allow us to do the following things:

  1. View all tasks in the list
  2. Add a new task to the list
  3. Edit a task to change its status
  4. View all completed tasks
  5. View all pen
  6. Delete a task
  7. A homepage that will allow access to all the features.

You may think that there is a huge gap between knowing what to make and actually making it. But wait! With Cake, that's not true at all! We are just 10 minutes away from the fully functional and working CakeTooDoo. Don't believe me? Just keep reading and you will find it out yourself.

Configuring Cake to Work with a Database

The first thing we need to do is to create the database that our application will use. Creating database for Cake applications are no different than any other database that you may have created before. But, we just need to follow a few simple naming rules or conventions while creating tables for our database. Once the database is in place, the next step is to tell Cake to use the database.

Time for Action: Creating and Configuring the Database

  1. Create a database named caketoodoo in the local machine's MySQL server. In your favourite MySQL client, execute the following code:
    CREATE DATABASE caketoodoo;
  2. In our newly created database, create a table named tasks, by running the following code in your MySQL client:
    USE caketoodoo; 
    CREATE TABLE tasks (
    id int(10) unsigned NOT NULL auto_increment,
    title varchar(255) NOT NULL,
    done tinyint(1) default NULL,
    created datetime default NULL,
    modified datetime default NULL,
    PRIMARY KEY (id)

  3. Rename the main cake directory to CakeTooDoo, if you haven't done that yet.
  4. Move inside the directory CakeTooDoo/app/config. In the config directory, there is a file named database.php.default. Rename this file to database.php.
  5. Open the database.php file with your favourite editor, and move to line number 73, where we will find an array named $default. This array contains database connection options. Assign login to the database user you will be using and password to the password of that user. Assign database to caketoodoo. If we are using the database user ahsan with password sims, the configuration will look like this:
    var $default = array( 
    'driver' => 'mysql',
    'persistent' => false,
    'host' => 'localhost',
    'port' => '',
    'login' => 'ahsan',
    'password' => 'sims',
    'database' => 'caketoodoo',
    'schema' => '',
    'prefix' => '',
    'encoding' => ''
  6. Now, let us check if Cake is being able to connect to the database. Fire up a browser, and point to http://localhost/CakeTooDoo/. We should get the default Cake page that will have the following two lines: Your database configuration file is present and Cake is able to connect to the database, as shown in the following screen shot. If you get the lines, we have successfully configured Cake to use the caketoodoo database.

    Create a Quick Application in CakePHP: Part 1

What Just Happened?

We just created our first database, following Cake convention, and configured Cake to use that database.

Our database, which we named caketoodoo, has only one table named task. It is a convention in Cake to have plural words for table names. Tasks, users, posts, and comments are all valid names for database tables in Cake. Our table tasks has a primary key named id. All tables in Cake applications' database must have id as the primary key for the table.

Conventions in CakePHP
Database tables used with CakePHP should have plural names. All database tables should have a field named id as the primary key of the table.

We then configured Cake to use the caketoodoo database. This was achieved by having a file named database.php in the configuration directory of the application. In database.php, we set the default database to caketoodoo. We also set the database username and password that Cake will use to connect to the database server.

Lastly, we made sure that Cake was able to connect to our database, by checking the default Cake page.

Conventions in Cake are what make the magic happen. By favoring convention over configuration, Cake makes productivity increase to a scary level without any loss to flexibility. We do not need to spend hours setting configuration values to just make the application run. Setting the database name is the only configuration that we will need, everything else will be figured out "automagically" by Cake. Throughout this article, we will get to know more conventions that Cake follows.


Writing our First Model

Now that Cake is configured to work with the caketoodoo database, it's time to write our first model. In Cake, each database table should have a corresponding model. The model will be responsible for accessing and modifying data in the table. As we know, our database has only one table named tasks. So, we will need to define only one model. Here is how we will be doing it:

Time for Action: Creating the Task Model

  1. Move into the directory CakeTooDoo/app/models. Here, create a file named task.php.
  2. In the file task.php, write the following code:
    class Task extends AppModel {
    var $name = 'Task';
  3. Make sure there are no white spaces or tabs before the <?php tag and after the ?> tag. Then save the file.

What Just Happened?

We just created our first Cake model for the database table tasks. All the models in a CakePHP application are placed in the directory named models in the app directory.

Conventions in CakePHP: All model files are kept in the directory named models under the app directory.

Normally, each database table will have a corresponding file (model) in this directory. The file name for a model has to be singular of the corresponding database table name followed by the .php extension. The model file for the tasks database table is therefore named task.php.

Conventions in CakePHP: The model filename should be singular of the corresponding database table name.

Models basically contain a PHP class. The name of the class is also singular of the database table name, but this time it is CamelCased. The name of our model is therefore Task.

Conventions in CakePHP: A model class name is also singular of the name of the database table that it represents.

You will notice that this class inherits another class named AppModel. All models in CakePHP must inherit this class.

The AppModel class inherits another class called Model. Model is a core CakePHP class that has all the basic functions to add, modify, delete, and access data from the database. By inheriting this class, all the models will also be able to call these functions, thus we do not need to define them separately each time we have a new model. All we need to do is to inherit the AppModel class for all our models.

We then defined a variable named $name in the Task'model, and assigned the name of the model to it. This is not mandatory, as Cake can figure out the name of the model automatically. But, it is a good practice to name it manually.

Writing our First Controller

With our Task Model in place, it is time to write our first controller. When a request is made to the web application, the controllers are where it is decided what should be done. In other words, controllers are where the application flow is controlled. If data needs to be accessed, the controller calls the models and fetches the data. The controller then sends the output to the views to be displayed. For CakeTooDoo, we will only need one controller called the Tasks Controller.

Time for Action: Creating the Tasks Controller

  1. Move into the directory CakeTooDoo/app/controllers. Create a file named tasks_controller.php.
  2. In the file tasks_controller.php, write the following code:
    class TasksController extends AppController {
    var $name = 'Tasks';
  3. Make sure there are no white spaces or tabs before the <?php tag and after the ?> tag. Then, save the file.

What Just Happened?

Like models, controllers in Cake are placed in a separate directory called controllers in the app directory. All the controllers in a Cake application must be placed in this directory.

Conventions in CakePHP: All controller class files are kept in the directory name controllers under the app directory.

Each model in the application has a corresponding controller in Cake. So, for our Task model, the corresponding controller is Tasks Controller.

It is not a must that all models have a corresponding controller, or vice versa. When we make more complicated applications, we will see that a controller may use more than one model if required.

The file name of the tasks controller is tasks_controller.php. It is a convention in Cake that controller file names are the plural of the model name followed by an underscore and the word controller, with .php extension.

Conventions in CakePHP: Controller filenames are plural of their model names, followed by an underscore and the word controller.

Like the model class, the controller class name is also CamelCased. In this case, it is TasksController. Notice that 'Tasks' is plural for the controller class name as in the controller file name. All Cake controllers must inherit from the AppController class.

Conventions in CakePHP: Controller class names should be CamelCased and plural.

AppController inherits the Controller class, which is a core class of CakePHP. The Controller class has all the basic functionalities that a controller needs to perform. As a result, by extending the AppController class, all controllers will have these functionalities and we do not need to define them again in our controllers.

Lastly, we defined the variable $name in the Tasks controller and assigned the name of the controller to it. Again, like models, Cake will be able to identify the name of the controller automatically, but it is always a good practice to add the $name variable in controllers.

Conventions in CakePHP: Model names are always singular, whereas controller names are always plural.

Viewing All Tasks in CakeTooDoo

Now that the Task model and the Tasks controller are in place, let us add some functionality to our application. The first thing that we would like to do is to view a list of all the tasks. To do this, we will need to add a function to the Tasks controller, and also add a view to show us the list of tasks.

Time for Action: Viewing All Tasks

  1. Open the file tasks_controller.php and add a method named index to the TasksController class with the following code. Any public functions inside controller classes are called actions. So, after adding the index action code to the TasksController class, our tasks_controller.php file will look like this:
    class TasksController extends AppController {
    var $name = 'Tasks';
    function index()
    $this->set('tasks', $this->Task->find('all'));
  2. Move into the directory CakeTooDoo/app/views. Create a directory named tasks inside the view directory.
  3. Inside the tasks directory that we just created, create a new file named index.ctp and add the following code to it:
    <?php if(empty($tasks)): ?>
    There are no tasks in this list
    <?php else: ?>
    <?php foreach ($tasks as $task): ?>
    <?php echo $task['Task']['title'] ?>
    if($task['Task']['done']) echo "Done";
    else echo "Pending";
    <?php echo $task['Task']['created'] ?>
    <?php echo $task['Task']['modified'] ?>
    <!-- actions on tasks will be added later -->
    <?php endforeach; ?>
    <?php endif; ?>
  4. Now point the browser to http://localhost/CakeTooDoo/tasks/index to view the list of all the tasks. Since we have not added any task, we should be getting a There are no tasks in this list message, as shown in the following screenshot:

    Create a Quick Application in CakePHP: Part 1

What Just Happened?

We created a controller method named index. Methods in controllers are called 'actions'. The index action, that we just added, handles a request whenever a request is made with the URL http://localhost/CakeTooDoo/tasks/index.

All Cake URLs have the following form: http://domainName/cakeApplicationFolder/controllerName/actionName

When a request is made to the index action, the following line is executed: $this->set('tasks', $this->Task->find('all'));. This line calls the function find() of the Task model that returns all the tasks stored in the tasks table.

All models in CakePHP have the find() function. It is actually defined in the Model Class. This function is used to fetch records from the table of the model. By passing parameters to this function, we can control which records we want to fetch. In the above code, all was passed to fetch all the records in the task table.

Then, using the set() function of the Tasks controller, it sends this data to the view in an array named tasks. We can access this array in the view through the $tasks variable.

The set() function is used to pass data from the controller action to the view. Two parameters are normally passed to it. The first is the name of the variable that the data will have in the view, and the second is the actual data that needs to be passed. The set() function is actually defined in the Controller class that is inherited by AppController, which again is inherited by all CakePHP controllers.

Like models and controllers, Cake also has a separate directory to place views. In the views directory, we created a directory named tasks that will hold all the views of the Tasks controller. As a controller can have many actions, and each action can have a view, a controller can have many views. Cake keeps all the views of a controller in its separate directory (with the same name as the controller) inside the views directory.

Conventions in CakePHP: All view files in Cake are kept in the views directory under the app directory. Inside this directory, all the views of a single controller are kept under a subdirectory with the same name as the controller.

Inside the tasks directory in views, we created a file named index.ctp. This is the view file of the index action of our Tasks controller. The action name and its corresponding view file name are always the same. Views always have the .ctp extension, which stands for Cake Template Pages.

Conventions in CakePHP The controller action and its corresponding view file have the same name.

In the index.ctp file, we placed the HTML code with embedded PHP code as well. Here, we have a HTML table to display all the tasks present in CakeTooDoo. Remember, that we sent an array named tasks to the view using the set() function in the index action? This array is accessible from the view, and using simple PHP codes, we display all the tasks that CakeTooDoo stored.

Adding a New Task

With the help of the index action and its view, we were able to display all the tasks in CakeTooDoo. But, because we did not add any task yet, the list displayed no tasks at all. So, let us add a form that will allow us to add tasks to CakeTooDoo. For this, we will need another action in our tasks controller and its corresponding view.

Time for Action: Creating the Add Task Form

  1. Open the file tasks_controller.php and add a new action named add as shown in the following code:

    function add() {
    if (!empty($this->data))
    { $this->Task->create();
    if ($this->Task->save($this->data)) {
    $this->Session->setFlash('The Task has been saved');

    $this->redirect(array('action'=>'index'), null, true);
    } else {
    $this->Session->setFlash('Task not saved. Try again.');
  2. In the same file(tasks_controller.php) add an array $helpers with the values as shown below:
    class TasksController extends AppController
    var $name = 'Tasks';
    var $helpers = array('Html', 'Form');
    function index() { ... }
    function add() { ... }
  3. Inside the directory /CakeTooDoo/app/views/tasks, create a new file named add.ctp and add the following code to it:
    <?php echo $form->create('Task');?>
    <legend>Add New Task</legend>
    echo $form->input('title');
    echo $form->input('done');
    <?php echo $form->end('Add Task');?>
  4. Now point the browser to http://localhost/CakeTooDoo/tasks/add to view the add task form. We should see a form as shown in the following screenshot:

    Create a Quick Application in CakePHP: Part 1

  5. Use the form to add the first task to CakeTooDoo and click on the submit button. This will redirect to the list all tasks page where you can view the added task.
  6. Now let us link the Task List and the Add Task Page. In the index.ctp file in /CakeTooDoo/app/views, add the following line at the end of the file:
    <?php echo $form->create('Task');?>
    <legend>Add New Task</legend>
    echo $form->input('title');
    echo $form->input('done');
    <?php echo $form->end('Add Task');?>
  7. To link the Add Task page to the View All Task page, add the following at the end of add.ctp file, found in /CakeTooDoo/app/views/:
    <?php echo $html->link('List All Tasks', array('action'=>'index')); ?>
  8. Now, go on to add more tasks to the list using the Add Task form we just created.


What Just Happened?

We added another action to the Tasks controller named add. This action can be accessed by pointing to the URL: http://localhost/tasks/add.

When a request is made to this action, it first checks whether any data has been sent via the POST method. Any data sent by POST method is automatically stored by Cake in the array $this->data of the controller. If no POST data is present, the add action does nothing, and the view is rendered showing the empty 'Add Task' form.

The view is automatically rendered when the action has finished executing.

When a filled up form is submitted, the submitted data is sent via POST, and stored in $this->data..When this happens, it calls the create() function of the Task model in the line: $this->Task->create();. The create() function prepares the Task model to add or edit data. Then, it calls the save() function of the Task model to save the data into our database using the code: $this->Task->save($this->data).

The functions create() and save() are two very useful model functions that are used frequently.

If the data is successfully saved, a success message is stored in the session and the page is redirected to the index action. The index action shows the newly added task, along with the success message stored in the session. If for some reason, the data was not saved in the database, an error message is stored in the session, and the add form is displayed again along with the error message.

We also added the HTML and Form helpers to the Tasks controller by adding the following line: var $helpers = array('Html', 'Form');.

Helpers are special modules of CakePHP that provide functions that are commonly needed in views to format and present data in useful ways.

Next, we create the view for the add action by adding the file add.ctp in the /CakeTooDoo/apps/views/tasks directory. In add.ctp, we first use the CakePHP Form helper to create a HTML form to accept data for the Tasks model using the code:

echo $form->create('Task');

The Form Helper has useful functions that help in creating HTML forms that can easily show or insert data using a Cake Model.

The HTML Input tags for entering the Title and Status of a task is created using echo $form->input('title'); and echo $form->input('done');. Lastly, we add echo $form->end('Add Task'); to close the form and add the submit button with the label 'Add Task'.

You will notice that the creation and modification times are not sent by the add form. This is because CakePHP automatically adds the time to fields that are of the type datetime and are named 'created' or 'modified'. Each time a task is added, Cake saves the time to the field 'created'. And whenever, a task is edited, it saves the time to the field 'modified'.

Lastly, we link the index (List All Tasks) and the add page (Add New Task) by using the HTML helper. Adding $html->link('Add Task', array('action'=>'add')); to index.ctp creates a hyperlink to the Add Task page. And adding $html->link('List All Tasks', array('action'=>' index')); to add.ctp adds a HTML hyperlink to the List All Task page.

There are many useful functions in the HTML helper that can make writing long HTML tags history. Here, we used the function link() that created HTML anchor tags. The first parameter passed to this function is the label of the link, and the second parameter is an array that points to the action to be linked to.

>> Continue Reading Create a Quick Application in CakePHP: Part 2


[ 1 | 2 ]

You've been reading an excerpt of:

CakePHP Application Development

Explore Title