Widgets with the Zend Framework and Smarty

Provided that you have checked my earlier tutorial on how to make instatiable controllers you could now use that functionality to create a widget system with Smarty.

What you need before we can start:
- A function in your controller(s) of choice that will use a Smarty object to return the HTML for the whatever widget you want to render with the Smarty fetch() method.
- The above mentioned ability to create instances of controllers.
- A factory function that will return instances of controllers, see my earlier tutorial for an example.

In the following example we will create some kind of menu that supposedly would look different depending on whether a user is signed in or not.

1.) Create Smarty insert functions that could look something like this:

function insert_getSessVar($params){
 $session = new Zend_Session_Namespace($params['nspace']);
 $sess_arr = $session->getIterator();
 return $sess_arr[ $params['key'] ];

function insert_getWidget($params){
 $controller = Factory::factory($params['ctrl']);
 $function = $params['func'];
 return $controller->$func($params);

2.) Call the above function in your markup with for instance:

{insert name="getSessVar" nspace=user key=online assign=online}
{insert name="getSessVar" nspace=user key=mood assign=mood}
{insert name="getWidget" ctrl=Menu func=getUserMenu style=$mood online=$online}

The above code will then call the getUserMenu in the Menu controller and pass the parameters to that function. In this case the only extra information is apparently a style that is set to whatever mood.

Why do we use the above convoluted way of determining the mood, why can’t we just check what kind of mood to use in getUserMenu() by checking the session there? The reason is that we want code separation, by having the mood passed to getUserMenu() we can use it without any changes whatsoever in other places.

Maybe you want an Ajax function that will change the mood of the user when the user changes mood in a drop down. Now you can have the Ajax function change the user’s mood in the session and redraw the menu without refreshing the page by using exactly the same getUserMenu(). And the next time the page refreshes the above code will see to it that the menu stays in the same mood.

Well then why don’t we just make sure we set the session variable in question to the proper value before we call getUserMenu() you might wonder? Sure you could do that, but having a test inside getUserMenu() to make sure the passed mood is not empty and giving off a warning if it is will make your life a hell of a lot easier than relying on the correct setting of session switches.

A more important reason to avoid session switches is that we would have a connection between the user session namespace and the menu controller which makes the menu less portable. You might be forced to change the source code of the menu controller if you want to implement the menu widget in some other project which doesn’t implement the same session namespace logic.

With the above way of doing things even some designer could port the menu widget to another project that might use it in a completely different way, unbelievable! For instance like this:

{insert name="getSessVar" nspace=user key=online assign=online}
{if $online eq "yes"}
{assign var="online_status" value="1"}
{assign var="online_status" value="0"}
{insert name="getWidget" ctrl=Menu func=getUserMenu style=black online=$online_status}

Related Posts

Tags: , , ,