The Magento Admin Console’s System Configuration section is almost an application framework in and of itself. The ability to quickly add form fields in a “zero code” way is a powerful feature, but it only touches the tip of the iceberg of what’s possible. This article will cover validating your configuration values, and sending appropriate error and/or warnings back to the end-user.
This article assumes an intermediate understanding of Magento coding conventions. You should be able to setup a new module for adding code to the system, configuring that module to use models, as well as configuring it to add a custom System Configuration field. If that all sounded greek to you, start reading
Let’s start by adding a custom module that sets up a System Configuration field for keeping track of a Store Fax Number.
Open up your Admin Panel and navigate to
System -> Configuration -> General -> Store Information
You should see three fields.
- Store Name
- Store Contact Telephone
- Store Contact Address
Create a custom module, and add a the following system.xml
file. For the purposes of this tutorial, we’ll be using a custom module named Validationexample
in the Alanstormdotcom
namespace.
<!-- File: app/code/local/Alanstormdotcom/Validationexample/etc/system.xml -->
<config>
<sections>
<general>
<groups>
<store_information>
<fields>
<alanstormdotcom_validationexample_fax translate="label">
<label>Store Fax Number</label>
<frontend_type>text</frontend_type>
<sort_order>20</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</alanstormdotcom_validationexample_fax>
</fields>
</store_information>
</groups>
</general>
</sections>
</config>
The alanstormdotcom_validationexample_fax
doesn’t need to be named that way. However, by going out of our way to to use a unique string for the final path in our configuration node, we help ensure there’s no possible conflicts with other modules that might want to setup a variable in the general/store_information
hierarchy.
Before we continue, reload the page (clearing your Magento cache if needed) and ensure that your new field is showing up.
Adding a Backend Model
Now that we have a field setup, lets get to setting up our field validation. We’re going to want to add a <backend_model />
node to our configuration.
<backend_model>alanstormdotcomvalidationexample/fax</backend_model>
The URI like string alanstormdotcomvalidationexample/fax
is a standard class alias that will be used to instantiate a model.
//you won't need to call this, but this is what magento will be doing behind the scenes
Mage::getModel('alanstormdotcomvalidationexample/fax');
The above example assumes you’re setup your module config for Models with something like
<models>
<alanstormdotcomvalidationexample>
<class>Alanstormdotcom_Validationexample_Model</class>
</alanstormdotcomvalidationexample>
</models>
If you’re not sure what that means a review may be in order.
So, let’s add the backend model to our system.xml
<alanstormdotcom_validationexample_fax translate="label">
<!-- NEW --> <backend_model>alanstormdotcomvalidationexample/fax</backend_model>
<label>Store Fax Number</label>
<frontend_type>text</frontend_type>
<sort_order>20</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</alanstormdotcom_validationexample_fax>
Next, enter a value for our new Store Fax Number field, and attempt to save it. You’ll see an error something like
Warning: include(Alanstormdotcom/Validationexample/Model/Fax.php) [function.include]: failed to open stream: No such file or directory in /path/to/magento/lib/Varien/Autoload.php on line 93
Magento has taken our class alias and attempted to instantiate it. Not finding a file for the class, PHP complains. We’d better one
#File: app/code/local/Alanstormdotcom/Validationexample/Model/Fax.php
class Alanstormdotcom_Validationexample_Model_Fax extends Mage_Core_Model_Config_Data
{
//empty for now
}
With that in place, let’s try a reload and/or saving again. The warning that halted execution should be gone, and your value should be properly saved.
Saving Configuration Data
Whenever you save a set of System Configuration options Magento scans the POST variables, and for each configuration field it finds it will instantiate a model object. That means for our configuration group, four objects are instantiated. One for Store Name, one for Store Contact Number, one for Store Contact Address, and finally one for our new Store Fax Number.
If no <backend_model/>
value is found, magento will use the Mage_Core_Model_Config_Data
class to instantiate the object. This Model knows how to save a configuration value. What we’ve done above is tell Magento to use our class instead of the default Mage_Core_Model_Config_Data
class. By extending Mage_Core_Model_Config_Data
we ensure that all existing functionality is maintained, and we can add our validation on top. The configuration system actually enforces this class hierarchy. If we attempt to extends from, say, Mage_Core_Model_Abstract
#File: app/code/local/Alanstormdotcom/Validationexample/Model/Fax.php
class Alanstormdotcom_Validationexample_Model_Fax extends Mage_Core_Model_Abstract
{
}
we’ll get an error something like
Invalid config field backend model: alanstormdotcomvalidationexample/fax
Your backend model must have Mage_Core_Model_Config_Data
in its inheritance chain.
Creating our Validation
So, we have a backend model. Now we need to add our validation method. The steps we’ll need to take are
- Redefine the
save
method in our class - Add some code to check the value of our class prior to saving
-
If that value doesn’t resemble a fax number, do something appropriate
-
Otherwise, call the parent class’s
save
method
This could look something like the following
#File: app/code/local/Alanstormdotcom/Validationexample/Model/Fax.php
class Alanstormdotcom_Validationexample_Model_Fax extends Mage_Core_Model_Config_Data
{
public function save()
{
$fax = $this->getValue(); //get the value from our config
$fax = preg_replace('#[^0-9]#','',$fax); //strip non numeric
if(strlen($fax) < 10) //exit if we're less than 10 digits long
{
exit("Fax Numbers need 10 digits. For American Numbers. Programming examples
are often horribly US-ethnocentric.");
}
return parent::save(); //call original save method so whatever happened
//before still happens (the value saves)
}
}
With the above code in place, try to save a fax number less than 10 digits long. You should see a white screen with
Fax Numbers need 10 digits. For American Numbers. Programming is horribly ethnocentric sometimes.
If you go back and enter a “proper” fax number, the value will save correctly.
So, we’ve added our validation, and it works. However, it’s not a friendly user error experience. Let’s try changing that exit
to the following
Mage::throwException("Fax Numbers need 10 digits. For American Numbers. Programming
examples are horribly US-ethnocentric sometimes.");
#exit("Fax Numbers need 10 digits. For American Numbers. Programming is
#horribly ethnocentric sometimes.");
Try saving a bogus fax number now, and you’ll end up with an error message being displayed without stopping execution.
The Magento Admin Console application is smart enough to take any Exception throw at this level, and display it back to the end user. This allows you, the end-user-programmer, to not worry about how errors are displayed. Run into a problem, throw an Exception, and be done with it.
Other Messaging Features
If you’ve spent anytime using Magento, you’ve probably seen the red error message box featured above. In fact, you’ve probably seen a green “everything went peachy” message box as well.
All Magento session objects have methods to allow you add these messages to your page. Said more accurately, all Magento session objects have methods that allow you to indicate a message should be sent to the end user, which is subsequently read by the messaging block in the layout, and displayed to the end user. When you throw an exception Magento is adding a message of type error to the session, with code that looks something like this
Mage::getSingleton('adminhtml/session')->addError('This is my error message. There are many like it, but this one in mine.');
As mentioned, this is a feature shared by all session objects, not just adminhtml/session
.
Mage::getSingleton('core/session')->addError('This is my error message. There are many like it, but this one in mine.');
In addition to errors, there are three other message types you may add: notices, warnings, and successes.
Mage::getSingleton('core/session')->addError('An Error');
Mage::getSingleton('core/session')->addWarning('A Warning');
Mage::getSingleton('core/session')->addNotice ('A Notice');
Mage::getSingleton('core/session')->addSuccess('A Success');
Less Strict
In our example above we were pretty inflexible about how we handled improperly entered fax numbers. If we wanted to be a little more flexible and encourage a 10 digit fax number rather than require one, we could change our backend model to notify the end-user that something doesn’t look right with their fax number, but allow them to save it anyway.
Let’s do that that by removing our save method, and adding a check in the _afterSave
method that will add a notice to request if something looks fishy about the fax number.
#File: app/code/local/Alanstormdotcom/Validationexample/Model/Fax.php
class Alanstormdotcom_Validationexample_Model_Fax extends Mage_Core_Model_Config_Data
{
public function _afterSave()
{
$fax = $this->getValue(); //get the value from our config
$fax = preg_replace('[^0-9]','',$fax); //strip non numberic
if(strlen($fax) < 10) //exit if we're less than 10 digits long
{
Mage::getSingleton('core/session')->addNotice('Fax numbers contains less than 10 digits. Please check your new value and change if desired.');
}
return parent::_afterSave();
}
}
With the above backend model in place, attempting to save a fax number with less than 10 digits should result in the following messages being displayed to the user.
Wrapup
Error handling is never glamorous. It’s often overlooked or over complicated in PHP frameworks, which leads to a morass of different validation styles and practices across an application. By leveraging Magento’s already powerful Model hierarchy and Session messaging system, not only can you provide a consistent experience for the users of your store, but also provide a consistent data validation pattern for your programming team.
Like this article? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.