Custom Smarty Plugins

One of Smarty’s big selling points is that you could easily extend it by writing your own custom plugins. Here are a couple…

A drop down box for countries:

{html_select_country}

function smarty_function_html_select_country($params, &$smarty)
{
   require_once($smarty->_get_plugin_filepath('function',
                'html_options');

   $options = array
   (
      'USA' => 'United States',
      'CAN' => 'Canada',
      .... <snip> ....
      'ZWE' => 'Zimbabwe'
   );

   $params['options'] = $options;

   return smarty_function_html_options($params, $smarty);
}

A drop down box for US states / Canadian provinces:

{html_select_state country = '<your country>'}

function smarty_function_html_select_state($params, &$smarty)
{
   require_once($smarty->_get_plugin_filepath('function',
                'html_options');

   $options = array();

   $usa_states = array
   (
      'AL' => 'Alabama',
      'AK' => 'Alaska',
      .... <snip> ....
      'WY' => 'Wyoming'
   );

   $can_provinces = array
   (
      'AB' => 'Alberta',
      'BC' => 'British Columbia',
      .... <snip> ....
      'YT' => 'Yukon Territories'
   );

   $country = $params['country'];

   switch($country)
   {
      case 'USA':
      case NULL;
      $options = $usa_states;

      default:
      $options = $can_provinces;
   }

   $params['options'] = $options;

   return smarty_function_html_options($params, $smarty);
}

Incidentally I’ve been using Smarty for about two years now and it was only until today that I actually wrote my very own custom plugin. I can’t believe how straight forward it was.

Form Validation

This week at the top of my TODO list is (server-side) form validation for The Project. Basically I need the following:

  1. User fills out the form and submits
  2. If user missed something or provided invalid input the form is redisplayed pre-filled with the data that has already been entered
  3. The redisplayed form indicates which field(s) need to be corrected
  4. Repeat #1 until form validates

Now the kind of validation that The Project needs is pretty standard stuff (email addresses, phone numbers, credit card numbers, street addresses) plus your usual suspects (non empty, alpha/numerical) so I figured there has to be a PHP form validation library out there that I could use. Besides I don’t like rolling my own stuff if I don’t have to.

And of course there are tonnes of such libraries out there but I decided to roll my own anyways!

Why?

Because after analyzing things a little more I realized all I needed/wanted was a ‘data validator’ class that would validate data in Step #2. Smarty and my event handler scripts could deal with Steps #1, #3, and #4 based on the data returned in Step #2.

So to write this ‘data validator’ class I downloaded a few of these PHP form validation libraries (SmartyValidate and ZendFramework actually) and copied their validation code for the various types that I needed. Thank you Open Source!

Infected By Ajax

The Project has this shopping cart form. Each product in the cart has its own <select> drop down for the product quantity and a <div> to show the product total price. A user can update the product qty by selected a different qty.

When I first created this form I made the page re-load when the user clicked a different quantity. Admittedly not very slick but easy-peasy to implement.

However The Client now wants the above to happen … wait for it… without a page load. The Project is officially infected by Ajax!

Well… 153 plain vanilla Javascript lines later I was finished. I’m a little embarrassed to share the code but suffice to say that:

  1. I’m sure that I or someone (or even a third party Javascript library) could make it more concise.
  2. It works across all (well Firefox, Opera, Safari, and IE 6/7) browsers.
  3. The Client is satisfied. And that’s what matters most.

I just hope that The Client doesn’t start to want this ajax thing everywhere in The Project.

I Love You Internet Explorer

The Project has this search form on the top of the page. The HTML looks like this:

<form action = "Search.do">
<input type = "text" name = "SearchTextBox">
<input type = "submit" name = "SearchButton" value = "Search">
</form>

Pretty standard stuff right? An input element and a submit button. The problem is that there’s only one input element. Apparently Internet Explorer doesn’t allow the Enter button to submit a form if there’s only one input element. WTF? OK no big deal just add a second (hidden) input field:

<form action = "Search.do">
<input type = "text" name = "SearchTextBox">
<input type = "text" style = "display: none">
<input type = "submit" name = "SearchButton" value = "Search">
</form>

Somehow I’m thinking this isn’t the most elegant solution out there but whatever… it works.

That Last Arrow Better Not Be An Object

Smarty gotcha #4982: Apparently you can’t easily display deeply nested objects in Smarty. For example you can do this:

<div>{$user->getAddress()->getCity()}</div>

You have to pull the nested object out and assign it to a temp variable:

{assign var = 'address' value = $user->getAddress()}
<div>{$address->getCity()}</div>

So just remember that the last arrow should not be an object.

As a side note… Is this difficult to implement/fix in Smarty? Or maybe this is Smarty’s way of saying ‘Don’t pass nested objects into your templates because this will easily confuse designers’?

Next Page →