CakePHP 4 - Saving and Validating Data

Skill

CakePHP 4 - Saving and Validating Data

Posted in:

Over our last few Cake tutorials, we have done a lot with so little code. We built a local website, set up our first Cake site, then finally used helpers to organize and make things look a bit nicer. Up until now we have been working with 2 measly database records. This has worked just fine until now, but we are going to need some more data for the tutorials to come.

To get more records, we are going to build a form that saves data to the database. Since we have a pretty basic cake setup right now, this will not be difficult. However, we are not only going to take in and save the data, but like all good websites, we are going to validate that data before we save it.

Magic Forms

The first thing we must do in our crusade for more data is create a form to gather the data. To do this, we are going to use the form helper and create what is called a "magic" form. The term "magic" is a fairly common PHP term, and it is simply stating that something is "magically" generated automatically from a few lines of code. In this case, we are taking 5 lines of code and turning them into a complete form. The magic part not only comes from the form generation but also from the fact that the form will be generated based on our database scheme, which is just cool.

To start you need to open up your view.ctp view, which can be found in your views/products folder. Right now, all we have is a table of data, which is neatly formatted with CSS. All we are going to do is create a form above everything else. All we need to do is add the following code to the top of the file:

<?php

echo $form->create();
echo $form->input('product_name');
echo $form->input('product_desc');  
echo $form->input('product_price');      
echo $form->end('Add');

?>

The Magic Form

Our Magic Form

The first line obviously created the form, and the last line ends it, calling the action we pass as the argument. What is really "magic" about this code is the lines in-between. Each line generates a form field, based on the database column we pass as the argument. So our description field will be a text area, and our price will be a text input that is only 5 characters long. With these five lines, we make a super-flexible form that changes with our database.

You may also notice that we are missing our product_id field altogether. Well if you recall, when we set up our database we setup our product_id field to auto-increment. Because of this, we don't really need to input the id, because it technically inputs itself.

Adding Validation Rules

In our previous tutorials, we have never really messed around with models. Today, however, we are going to add a little to our products model. This is because most of the validation rules are on the model side of things. So, you will need to open your Product.php file, which can be found in the app/models folder. Right now, your model should be pretty empty:

<?php

class Product extends AppModel
{
  var $name = "Product";
}

?>

Nothing exciting going on there. What we need to add is a validation rule for our price, so it can only accept a 2 digit decimal number. Luckily for us, this type of mundane validation is built right into Cake. To add this rule, we are going to add a $validate variable to our model class. Once added, this rule will pass over our data every time it is saved. Our final model will look like this:

<?php

class Product extends AppModel
{
  var $name = "Product";
  var $validate = array(
    'product_price' => array(
      'rule' => array('decimal', 2),
      'message' => 'Price must be a number!'
      )
    );
}

?>

Now take notice that the $validate variable is a multi-dimensional array, with the first array set being an array of column names. Each column name then has an array of options, in this case the options of rule and message. The rule is obviously the validation rule, and the message is the validation failure message. Now the rule option can be all kinds of things, but in our case we set have it set to check for a decimal with a maximum of 2 digits behind the decimal place. None of our other fields need validating at this point, so our validation rules are done. Simple enough.

Validating and Saving

To complete the MVC circle, we now have to add to our controller. In fact, we have to add quite a bit to our controller. So go ahead and open our products_controller.php up, which is in the app/controllers folder.

Now the first thing we have to do in our controller is add a new function to the controller class, or more precisely, add a new action to it. Now, our "magic" form not only creates and maintains our form for us, but will also call the correct action on submission. This action call depends on a few different things, but for our case it is calling the add action.

Inside this action, we need to do 3 key things: validate our form data, save it, then redirect to the default action. Normally, the data to save is only validated when you call the save() method in your controller, but we can also validate before we try to save anything. This not only double validates our data, but allows us to give some user friendly feedback if something goes wrong.

Once our data validates and is saved, we need to redirect to the default page, thus creating a loop. With this loop of data entry, we can add as many records to the database as we want. For example sake, this is what the final controller will look like:

<?php

class ProductsController extends AppController
{
  var $name = "Products";
  var $helpers = array('Html', 'Session');
 
  function index()
  {
    $data = $this->Product->find('all');
    $this->set('data', $data);
  }
 
  function add()
  {
    $this->Product->set($this->data);
   
    if ($this->Product->validates())
    {
      if($this->Product->save($this->data))
        $this->Session->setFlash('Data Saved Successfully!');        
    }
    else
    {
      $errors = $this->Product->invalidFields();
      $this->Session->setFlash(implode(',', $errors));    
    }
   
    $this->redirect(array(
      'controller' => 'products',
      'action' => 'index'
      )
    );    
  }
}

?>

The first thing that we changed is our $helpers array, which we added the session helper too. There is one key reason for doing this, the flash object. This object helps use post alerts to the user, over multiple pages. The session helper can do a lot more, but for our purposes today, the flash messages will be all we need.

Next, you will notice that we are calling a set() method on our data object provided by Cake. This allows us to set the data to be saved, without actually saving it. The $this->data call we pass as the argument refers to the form data, which is saved in the data variable of the controller class.

Once the form data is passed to the product data object, we need to validate it. To do this, we use an if statement, which tests the return of a validate() method of the product data object. This method takes our rules from the model and applies them to the current data, in this case, our form data. It will return true if it validates and false otherwise. So if we get back true, we save our data.

To save the data, we call the save() method. This method takes the data we set earlier and saves it to the database, running it through the validation yet again along the way. The method returns true if it saves successfully, so we test for that as well. If everything goes OK, then we set the flash message to a nice and friendly "data saved" message.

Data Saved!

Successfully Saved Data

If, for whatever reason, the form data does not validate, we need to first find out why. The invalidFields() method is a perfect way to do this. It returns an array of error messages provided from our model's $validate array. So when we set a variable to the method's return array, we need to display them. So we take the array, glue it together with implode, then pass it to our flash message. This will display any error we may encounter from the validation.

So, we end up with a convenient way to add a whole bunch of records to our database, all using Cake. This is not really a practical website, but it does teach you a lot about how CakePHP handles data entry and validation. Like most things, Cake makes it quite simple and straight forward, as long as you follow its conventions.

Well, this just about wraps it up for this tutorial. I hope you learned a lot today. Just remember, when you need coding help, just Switch On The Code.

Nandakumar M V
08/11/2009 - 00:17

Good one

reply

Anonymous
12/22/2009 - 21:51

that okay....but what if i need to bypass the validation when i am doing update of data for example user updating his email id only
-------
libmaker

reply

Amol Bhavsar
04/23/2010 - 08:25

I have read your tutorials on CakePHP. And it were so useful that I can not explain it.

Nice job, Dear!

reply

Anonymous111
06/24/2010 - 09:41

Display the errors as one big message is s**t! Cake gives it separate, why throw away useful data? Can you do it so that each field has it relevant error message next to it?

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.

Sponsors