on Tutorials

CakePHP from scratch: Data validation, routes and more

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

In the previous tutorial I showed you how to develop small application using only one database table. We added Model, Controller and Views for listing and adding Categories in our table. Anyway, today we will continue, so open up the files you created in the previous tutorial (or if you did not finish it, go and check it out now).

I would like to touch an issue of data validation first, and then build the rest of functionality for editing and deleting content of our Categories table.

Data validation in CakePHP is done in Model. And it is quite easy to add it. As our table has only one field to validate, we will just add validation that this field can not be empty. So, replace the code in your /app/models/category.php so it looks like this:

class Category extends AppModel {
    var $name = 'Category';
    
    var $validate = array(
        'name' => array(
            'rule' => 'notEmpty'
        )
    );
}

The $validate array tells CakePHP how to validate your data when the save() method is called. Here, I’ve specified that name field must not be empty. CakePHP’s validation engine is strong, with a number of pre-built rules (credit card numbers, email addresses, etc.) and flexibility for adding your own validation rules and will be covered in more details when I extend the tutorial to build a Jobs board application.

Data validation is an important part of any application, as it helps to make sure that the data in a Model conforms to the business rules of the application.

Now that you have your validation rules in place, use the app to try to add a category with an empty name to see how it works. Since we’ve used the input() method of the FormHelper to create our form elements, our validation error messages will be shown automatically.

You can even write your own error messages. Try this in your model file:

class Category extends AppModel {
    var $name = 'Category';
    
    var $validate = array(
        'name' => array(
            'rule' => 'notEmpty',
            'message' => 'No, no, this field must not be empty!'
        )
    );
}

Try saving Category without a name and your custom message should appear. Great stuff.

Let us develop our functionality for editing and deleting the categories. First, easy one – deleting. Open up your /app/controllers/categories_controller.php file and add this function in it just below your add function:

function delete($id) {
        $this->Category->delete($id);
        $this->Session->setFlash('The category with id: '.$id.' has been deleted.');
        $this->redirect(array('action'=>'index'));
    }

As this function only deletes the category and redirects back to index action of the Categories controller, we don’t have to create a view. However, we will change our index view to have links for deleting a specific category. Open up your /app/view/categories/index.ctp file and change to look like this:

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

<h1>Categories</h1>

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

<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Actions</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' => 'edit', $category['Category']['id'])); ?>
        </td>
        <td>
        <?php echo $html->link('Delete', array('action' => 'delete', $category['Category']['id']), null, 'Are you sure?' )?>
        </td>
    </tr>
    <?php endforeach; ?>

</table>

Try to delete some categories now. Did you notice that CakePHP automatically generated a Javascript confirm dialog that asks the user Are you sure? . How awesome is that?

Next, we will add function for editing categories in our controller. Add this in your /app/controllers/categories_controller.php file:

function edit($id = null) {
        $this->Category->id = $id;
        if (empty($this->data)) {
            $this->data = $this->Category->read();
        } else {
            if ($this->Category->save($this->data)) {
                $this->Session->setFlash('Your category has been updated.');
                $this->redirect(array('action' => 'index'));
            }
        }
    }

This function first checks for submitted form data. If nothing was submitted, it finds the Category and hands it to the view. If some data has been submitted, try to save the data using Category model (or kick back and show the user the validation errors).

We need a view for this, so create /app/views/categories/edit.ctp file and paste in this code:

<h1>Edit Category</h1>
<?php
    echo $form->create('Category', array('action' => 'edit'));
    echo $form->input('name');
    echo $form->input('id', array('type'=>'hidden')); 
    echo $form->end('Save Category');
?>

This view outputs the edit form (with the values populated), along with any necessary validation error messages.

One thing to note here: CakePHP will assume that you are editing a model if the ‘id’ field is present in the data array. If no ‘id’ is present (look back at our add view), Cake will assume that you are inserting a new model when save() is called.

You can now update your index view with links to edit specific categories, so /app/views/categories/index.ctp now looks like this:

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

<h1>Categories</h1>

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

<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Actions</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' => 'edit', $category['Category']['id'])); ?>
        </td>
        <td>
        <?php echo $html->link('Delete', array('action' => 'delete', $category['Category']['id']), null, 'Are you sure?' )?>
        <?php echo $html->link('Edit', array('action'=>'edit', $category['Category']['id']));?>
        </td>
    </tr>
    <?php endforeach; ?>

</table>

Congratulations, you finished your first CakePHP application!

Let me explain a bit about Routing in CakePHP. For some, CakePHP’s default routing works well enough. Developers who are sensitive to user-friendliness and general search engine compatibility will appreciate the way that CakePHP’s URLs map to specific actions. So we’ll just make a quick change to routes in this tutorial.

By default, CakePHP responds to a request for the root of your site (i.e. http://www.example.com) using its PagesController, rendering a view called “home”. Instead, we’ll replace this with our CategoriesController by creating a routing rule.

Cake’s routing is found in /app/config/routes.php. You’ll want to comment out or remove the line that defines the default root route. It looks like this:

Router::connect ('/', array('controller'=>'pages', 'action'=>'display', 'home'));

Now add this line directly below the one you commented:

Router::connect ('/', array('controller'=>'categories', 'action'=>'index'));

This will connect users requesting ‘/’ to the index() action of our CategoriesController. Point your browser to http://localhost/cake (or wherever you have your application) and you will see that it works awesomely.

Make sure your read our previous tutorials in CakePHP series:

Stay tuned as we will continue next time with CakePHP Bake generator.

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



  • Mike

    Is there a list of all Validation Rules in CakePHP?

    Or is this coming up in one of following tutorials? 🙂

  • Pingback: CakePHP from scratch: Baking our application()

  • Pingback: CakePHP from Scratch: Theming in real life example – Part Two()

  • This is a very well-written piece on adding/editing/deleting records in your cakephp application. I wish I’d seen this earlier, as other tutorials always seem to miss important information (or it’s easy to forget an instruction). The best piece of advice to a beginner in cakephp, I feel, is to always make sure your primary key field in any table is called `id` and to populate it automatically using auto-increment. Fairly basic stuff I suppose, but you soon get found out if you forget to implement this standard. Anyway, enough of my rambling, just here to say well done, a fantastic tutorial on cakephp!

  • Hello,

    I tried the same for my employee model employee.php for the username field “employeeUsername” as the following, but it didnt work. 🙁 Can you please advice

    class Employee extends AppModel {
    var $name = ‘Employee’;
    var $validate = array(
    ’employeeUsername’ => array(
    ‘rule’ => ‘notEmpty’,
    ‘message’ => ‘Alphabets and numbers only’
    )
    );
    }

    • Hi Ginnu,

      could you please explain in more details what is not working. Above code should work.

  • You know brother i am fan of your CakePHP tutorials, really amazing, easy and clean.

    Thanks for sharing this 🙂