Magento custom model with custom validation rules

Featured Image

Creating your own Magento module usually goes along with creating your own models within the module. Either you write one or multiple models per module, its a good idea to implement model validation method which you might/should call prior to model save. Good example of Magento’s model that use validation are Mage_Customer_Model_Customer and Mage_Customer_Model_Address_Abstract models. Quick look into the “public function validate()” methods of those two models reveal the simplicity of validation process.

Usually the validation is done by utilizing the available Zend validation method “Zend_Validate::is($filter)” with various built in filters. Here are few examples:

if (!Zend_Validate::is( trim($this->getFirstname()) , 'NotEmpty')) {
	$errors[] = $customerHelper->__('The first name cannot be empty.');
}
 
if (!Zend_Validate::is( trim($this->getLastname()) , 'NotEmpty')) {
	$errors[] = $customerHelper->__('The last name cannot be empty.');
}
 
if (!Zend_Validate::is($this->getEmail(), 'EmailAddress')) {
	$errors[] = $customerHelper->__('Invalid email address "%s".', $this->getEmail());
}
 
$password = $this->getPassword();
if (!$this->getId() && !Zend_Validate::is($password , 'NotEmpty')) {
	$errors[] = $customerHelper->__('The password cannot be empty.');
}
if ($password && !Zend_Validate::is($password, 'StringLength', array(6))) {
	$errors[] = $customerHelper->__('The minimum password length is %s', 6);
}
$confirmation = $this->getConfirmation();
if ($password != $confirmation) {
	$errors[] = $customerHelper->__('Please make sure your passwords match.');
}
 
if (('req' === $addressHelper->getConfig('dob_show'))
	&& '' == trim($this->getDob())) {
	$errors[] = $customerHelper->__('The Date of Birth is required.');
}
if (('req' === $addressHelper->getConfig('taxvat_show'))
	&& '' == trim($this->getTaxvat())) {
	$errors[] = $customerHelper->__('The TAX/VAT number is required.');
}
if (('req' === $addressHelper->getConfig('gender_show'))
	&& '' == trim($this->getGender())) {
	$errors[] = $customerHelper->__('Gender is required.');
}

To help you both visualize and put into practical usage, I have coded this sample module that has two models define, User and Account model. Once you install the module, it will create two database tables, each for one of the models. You can instantiate models by using like:

$user = Mage::getModel('mve/user');
$account = Mage::getModel('mve/account');

Practical example is given in the controller class Ajzele_ModelValidationExample_IndexController. There you will see two action methods, one called testUserModelValidationAction, other testAccountModelValidationAction. You can test them out by opening the urls:

https://mysite.net/ajzeleModelValidationExample/index/testUserModelValidation
and
https://mysite.net/ajzeleModelValidationExample/index/testAccountModelValidation

in your web browser.

Analyzing the code in those two action methods you can clearly see I am instantiating the models then running validation on each before attempting to save them. Results of validation or possible save errors are saved in the /var/log/system.xml file. Please rememeber to turn on the loging functionality in Magento, via System > Configuration > Advanced > Developer > Log.
In order to figure out what properties/fields you can set on each model, please examine the modules mysql4-install-1.0.0.php file.

User model allows you to set “firstname”, “lastname” “email”, “is_vip” properties/fields. Here is an example of validation method for User model.

public function validate()
{
	$errors = array();
	$helper = Mage::helper('mve');
 
	if (!Zend_Validate::is($this->getFirstname(), 'NotEmpty')) {
		$errors[] = $helper->__('Please enter the first name.');
	}
 
	if (!Zend_Validate::is($this->getLastname(), 'NotEmpty')) {
		$errors[] = $helper->__('Please enter the last name.');
	}
 
	if (!Zend_Validate::is($this->getEmail(), 'EmailAddress')) {
		$errors[] = $helper->__('Invalid email address "%s".', $this->getEmail());
	}  
 
	if (!Zend_Validate::is($this->getIsVip(), 'NotEmpty')) {
		$errors[] = $helper->__('Please define true/false for isVip condition.');
	}         
 
	if (empty($errors) || $this->getShouldIgnoreValidation()) {
		return true;
	}
	return $errors;
}  

Account model allows you to set “account_type”, “user_id” properties/fields. And here is an example of validation method for Account model.

public function validate()
{
	$errors = array();
	$helper = Mage::helper('mve');
 
	if(!in_array($this->getAccountType(), $this->_accountTypes)) {
		$errors[] = $helper->__('Invalid account type. Please use one of these: %s.', implode(', ', $this->_accountTypes));
	}
 
	if (!Zend_Validate::is($this->getUserId(), 'Int')) {
		$errors[] = $helper->__('Please use integer value for "user_id" field.');
	}
 
	if (empty($errors) || $this->getShouldIgnoreValidation()) {
		return true;
	}
	return $errors;
}  

As you can see, validation methods can be pretty simple, as you can get a lot of help from built in Zend libraries.

With that in mind, and depending on your model types and functionality I would strongly encourage you to validate your models before saving them. Saving log records for invalid validation can help you a lot in certain scenarios.

And here is an example module for download, Ajzele_ModelValidationExample.

Also, just for the reference, this module has been built on Magento 1.4.1.1.

Cheers.


6 comments

  1. Hi Branko,

    I would like to create a new page for user to change or update their password. I have created the phtml file asking for CURRENT PASSWORD, NEW PASSWORD AND CONFIRM PASSWORD. How to validate this or any controller action for this? Thanks!

  2. Hi,

    good working, anyone can easily understand.

    actually here we are saving logs file If I want to show the front-end and helight that field how?

    can you give me a example for

    how to make a custom field is required?

    thanks in advance.

  3. Hi Branko,

    It is always nice idea to have validation. For example I prefer to define validation rules in config.xml and read them. It helps to make system more flexible and alows me to get rid of modifying code if customer wants change some validation rule.

    PS: Please fix typos in both examples, “emptyempty” seems should produce a fatal.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.