on Tutorials

CakePHP from scratch: Making a small application in CakePHP

9 comments
cakephp1
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon

In the previous tutorials I explained some basics about CakePHP framework. You can find those tutorials by viewing the articles in CakePHP tag.

This time we are actually going to build something working. It will be a one table small example that we will use later and expand into a whole web application. If you are wondering, I will build a full Jobs board web application with user registration, login, adding jobs to the listings, browsing this jobs, applying to job offers etc. More details next time.

I presume that you followed previous tutorials and have CakePHP ready, connected to database. If not, please do so now.

Today I will build a MVC architecture for a categories table. For better understanding of CakePHP framework, I will manually create Model, Controller and Views for this fairly simple table. You are wondering what does this guy talk about? Manually? Is there another way? Well yes, you will see at the end of this tutorial.

First we will create a table in our database:

CREATE TABLE `categories` (
  `id` INTEGER(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM

Our first step is over. As mentioned before, CakePHP is all about Convention over Configuration, so it is important that you understand its naming conventions. Usually, table names are in plural.

To start our MVC philosophy, I will create a model for this table. CakePHP models are located in /app/models folder. So, create a file called category.php in /app/models folder and copy/paste this code into it:

<?php
class Category extends AppModel {
    var $name = 'Category';
}
?>

This is everything we need inside our model. As you can see, naming convention for models is that file and class names are in singular. What I just wrote? Well, I extended CakePHP’s AppModel class and declared a variable $name which will be used from our Controller to access the model’s functions.

CakePHP stores controllers in /app/controllers folder. So, create a file named categories_controller.php in /app/controllers and paste this code in:

<?php
class CategoriesController extends AppController {

	var $name = 'Categories';

	function index() {
		$this->set('categories', $this->Category->find('all'));
	}
}
?>

Wow, a little bit longer code this time. We are extending AppController class, declaring $name variable. This time I added a function called index. The controller functions are called actions.

Let me explain the action a bit. By defining function index() in our CategoriesController, users can now access the logic there by requesting www.example.com/categories/index. Similarly, if we were to define a function called foobar(), users would be able to access that at www.example.com/categories/foobar.

You may be tempted to name your controllers and actions a certain way to obtain a certain URL. Resist that temptation. Follow CakePHP conventions (plural controller names, etc.) and create readable, understandable action names. You can map URLs to your code using “routes” which I will cover in future tutorials.

Consider this line in above code in index() function:

$this->set('categories', $this->Category->find('all'));

This is why I love CakePHP. With this one line of code, we are selecting all categories from categories table and assigning the resulting array to categories variable. This variable will be available in our index view. Let us create it.

Cake’s view files are stored in /app/views inside a folder named after the controller they correspond to (we’ll have to create a folder named categories in this case). Create a file index.ctp in /app/views/categories folder. Ctp files are CakePHP template files. Paste this code in:

<!-- File: /app/views/categories/index.ctp -->

<h1>Categories</h1>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
    </tr>

    <?php foreach ($categories as $category): ?>
    <tr>
        <td><?php echo $category['Category']['id']; ?></td>
        <td>
            <?php echo $html->link($category['Category']['name'], 
array('controller' => 'categories', 'action' => 'view', $category['Category']['id'])); ?>
        </td>
    </tr>
    <?php endforeach; ?>

</table>

Let me explain. As you can see, index.ctp is simple HTML and PHP mixed file. If you remember, we added all categories to a categories variable, so we can directly use it in our foreach loop. I am just writing data to a table. To test what you have done, go to your cake install URL and add /categories (for example http://localhost/cake/categories). You should see your data in a table.

If you noticed, I am using $html object to generate a link. I will explain this later. This code generates a link to /categories/view/category_id . In this example we will not use it, but it could be interesting to have this functionality if you are writing MVC code for articles table.

Let me spice things up a bit. Change your categories_controller.php file to this:

class CategoriesController extends AppController {

    var $name = 'Categories';

    function index() {
        $this->set('categories', $this->Category->find('all'));
    }
    
    function add() {
        if (!empty($this->data)) {
            if ($this->Category->save($this->data)) {
                $this->Session->setFlash('Your category has been saved.');
                $this->redirect(array('action' => 'index'));
            }
        }
    }
}

I added a function add(). This function is all you need to save data to categories table. The function is checking if variable data is full. This variable is used to store data posted from forms. Then the function is saving the data, writing a nice message and redirecting back to index function.

Let me create the view for this:

<!-- File: /app/views/categories/add.ctp -->    
    
<h1>Add Category</h1>
<?php
echo $form->create('Category');
echo $form->input('name');
echo $form->end('Save Post');
?>

I am using CakePHP’s form helper to create the form. Point your browser to your application and use add as action this time (for example http://localhost/cake/categories/add ). You should see the form rendered and ready to rock. If you view the source and check the generated source, you will see that Cake automagically transformed this code onto a valid form.

Let me explain a form helper, as it is important. If create() is called with no parameters supplied, it assumes you are building a form that submits to the current controller’s add() action (or edit() action when id is included in the form data), via POST.

The $form->input() method is used to create form elements of the same name. The first parameter tells CakePHP which field they correspond to, and the second parameter allows you to specify a wide array of options – in this case, the number of rows for the textarea. There’s a bit of introspection and automagic here: input() will output different form elements based on the model field specified.

The $form->end() call generates a submit button and ends the form. If a string is supplied as the first parameter to end(), the FormHelper outputs a submit button named accordingly along with the closing form tag.

Now let’s go back and update our /app/views/categories/index.ctp view to include a new “Add Post” link. Just after

<h1>Categories</h1>

add:

<?php echo $html->link('Add Category',array('controller' => 'categories', 'action' => 'add')); ?>

I think that this is enough for today. Next time I will finish this by adding data validation, edit and delete functionality. I think that you are seeing the small amount of code needed to code this.

And I mentioned in the beginning that there is another way of doing this. CakePHP comes with automagic generator which generates MVC code according to your database schema! But that will be covered in details later.

So, stay tuned.

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon