Is calling object methods from templates (smarty) ok?

I will be redesigning code for a large website which uses Smarty and currently has 3 skins (3 separate sets of Smarty templates to display the same data). I will be keeping the templates as they are but write the application code from scratch since the current one is 7 year old and one big mess.

In many cases data are passed to Smarty in arrays and templates access those arrays like this:


<h2>{$product.name}</h2>
<p>{$product.short_description}</p>
<p><a href="{$product.link}">more info</a></p>
<p><a href="{$product.link}#accessories">Accessories ({$product.accessories_count})</a></p>

This is just a simplified example. Now I will be using a sort of active record in the application layer so in such cases it would be convenient to use objects directly like this:


<h2>{$product->name}</h2>
<p>{$product->short_description}</p>
<p><a href="{$product->getPageLink()}">more info</a></p>
<p><a href="{$product->getPageLink()}#accessories">Accessories ({$product->countAccessories()})</a></p>

So you can see that to objects having primarily data from db I will add many convenience methods like getPageLink() or countAccessories(). For me accessing those methods from within the templates is very convenient when I code but is this good design? Is accessing methods right for a template? Template designers should generally be not bothered with underlying business logic and I am wondering if methods should be used within templates. I use methods all the time in administration panels and I see no problem with this but this time I would use them in templates that will probably be edited by other people as well - designers who are not interested in my application code underneath.

What do you think? My question is what is your preference and how would you go about this? My current ideas are:

  1. Either recode the templates to use objects and methods and make it easier to maintain for me - the application coder
  2. Or leave the templates as they are and in the php code translate all necessary data from objects to arrays and pass only arrays to Smarty. This will not bother template designers at all but will add to the amount of code I will need to write.

but I’m still not sure which way is the better way, or perhaps there is a third way?

So long as the methods handle display logic and don’t impede on the controllers responsibilities.

This is the method in which the views in my current application are set up. Each view is a class which makes it very easy to encapsulate display functionality into separate methods. HTML template files don’t exist.

It is good that you are trying to separate concerns, you feel and probably have heard that templating is some form of best practice, but the how and why is somewhat vague to you. I know what it feels like.
Templates are a means to separate “business logic” from the view. Business logic is something like update a record in the database, checking rights etc.
There is one rule: the view may access data, but not change it!

So: is accessing data from an object right? Yes, it is!
There is a design pattern that is the defacto standard for good web application design: Model View Controller (MVC)

The Model contains all data and rules about your domain (for instance: bicycles, customers, cats, processes).

The View asks for data and displays it somehow. Nor the model nor the controller should dictate how information is presented. It is up to the View.

The Controller should be thin: given an request (bicycles.com/product/345) it instantiates the appropriate view (template) and tells it to render.
If an invalid request is made, the controller should do a redirect to an error page, log it or what else. The controller is a delegating object.
On the internet many examples are shown of a controller class

  1. that gets a certain database identifier from a request
  2. pulls the data out of the database
  3. instantiate a template with only variables like you’ve shown
  4. and say: template->render();

Well that’s a nice controller, except the 3rd item. One should strive for thin controllers. The View should get the data it wants.

In you controller you have:


// file: ProductController.php
$view = new TemplatingSystem();
$view->productId = $_GET['product-id'];

So in your template you ideally have

<?php
// file: products.tpl
// $this is the template object. In smarty it is $smarty
$bicycle = Bicycles::getById($this->productId)
echo 'model: ', $bicycle->model;
//etc
?>

I recommend reading http://blog.astrumfutura.com/archives/353-An-Example-Zend-Framework-Blog-Application-Part-2-The-MVC-Application-Architecture.html since it will teach you a lot about MVC.

I’ve used smarty in the past, and it has been a very bad choice. You’d better of with Savant or Zend_View from Zend framework [Zend View is a modification of Savant].

In conclusion:

  1. Writing your own MVC-framework is hard. I recommend picking an existing one.
  2. Smarty is a bad choice: working with real php objects is only easy in real php, not some cumbersome limiting syntax.
  3. Zend Framework supports Smarty too, if refactoring is a too big burden.

class Foo {
  public $name = 'whatever';
}

$foo = new Foo();
echo $foo->name;

Accessing a property of a object isn’t business logic. Business logic is merely communication between the domain and database.

Without a database you still can have business logic. I don’t think this is a good definition. I think of b.l. as rules that are applied on your domain data.
Accessing a property of an object is indeed not necessarily busines logic (it could trigger some b.l. rules however in theory).

But that’s completely not the point I wanted to make. My message is: separate your domain (data, rules, policies) from your view.

It could but generally it is the responsibility of the controller to initiate that transaction not the views.

No. An application without persistence can have a lot of business logic.

On topic: I too do access object properties from smarty templates but I usually prefer to pass - i.e. $template->assign() - dumb data objects, preferably arrays. Just make sure no part of the view changes the application’s state.

Thanks everyone for the answers, the general consensus seems to be that views and templates can access properties and methods but not change them.

I don’t want to discuss here whether Smarty is good or not, it serves its purpose well in this project and there’s no need to rewrite everything at this point.

What do you mean by dumb data objects?

In Java I’d prefer using a passive interface (no setters, only getters) to make sure the template coder does not change state. In PHP I either pass simple data types like


$template->assign('id', $user->getId());
$template->assign('name', $user->getName());

or if necessary an array (that’s what I called dumb data object):


$userArray = array('id' => $user->getId(), 'name' => $user->getName());
$template->assign('user', $userArray);

Where a User class has the properties id and name.

This is also useful because (I think) I recall in Smarty you can’t do chaining:

{$thing->getUser()->getName()}

Is this correct? It’s been some time since I tried this.

Well, that was my main question to start with and this is the option 2 from my initial post:

  1. Or leave the templates as they are and in the php code translate all necessary data from objects to arrays and pass only arrays to Smarty. This will not bother template designers at all but will add to the amount of code I will need to write.

I’m wondering if it’s better to use this kind of dumb data object or simply pass the object, which seems less work.

This is also useful because (I think) I recall in Smarty you can’t do chaining:

{$thing->getUser()->getName()}

Is this correct? It’s been some time since I tried this.

Yes, it’s correct. But I find those cases are rare when I need to use chaining, however it’s a nice feature missing now in Smarty. I know there is a patch for Smarty if someone really wants it.

Chaining is considered evil anyway:

So I’d rather not patch this behaviour.

It is better to not let the controller pass the data to the view. Your controller should be thin; the view should query your domain for the data it wants to display. Why? Because if you need to reuse a template elsewhere, you find yourself duplicating code in different controllers.

When you put aside this requirement you get the strange question whether you should turn the data into some other form just to please the template. Turning the data structures into other structures is unnecessary. So ideally you use the real objects.
I can imagine that it can be a lot of work to rewrite all the templates, but writing procedures to turn format a into b will likely be the same amount of work.

Yes, it’s correct. But I find those cases are rare when I need to use chaining, however it’s a nice feature missing now in Smarty. I know there is a patch for Smarty if someone really wants it.

See how stupid smarty is. Before I used to think it helps me, but it does nothing more than php. It offers a strange syntax that is less expressive than php itself.
I recommend reading http://nosmarty.net/articles/2008/08/08/is-smarty-right-for-me/ for any future project.

Hm, that’s way too fast. Method chaining is ok, but it can sometimes be a bad smell. If software design could be done by such easy rules solely, than software engineering would be really simple. Unfortunately, this isn’t the case.

A disadvantage of the Law of Demeter is that it sometimes requires writing a large number of small “wrapper” methods (sometimes referred to as Demeter Transmogrifiers) to propagate method calls to the components. Furthermore, a class’s interface can become bulky as it hosts methods for contained classes resulting in a class without a cohesive interface.

Interesting read, thanks. But it looks like a debatable law, doesn’t it?

That is a valid point, thanks. I also was thinking about it. Translation seems unnecessary.

See how stupid smarty is. Before I used to think it helps me, but it does nothing more than php. It offers a strange syntax that is less expressive than php itself.
I recommend reading http://nosmarty.net/articles/2008/08/08/is-smarty-right-for-me/ for any future project.

I have worked with smarty and with php-based templates and smarty is quite convenient - in rare cases some features are missing compared to pure php but in frequent cases the simplicity of syntax is nice and can save a lot of typing. I’ve already read many debates for and against smarty so please don’t start another one in this thread.

Hm, that’s way too fast. Method chaining is ok, but it can sometimes be a bad smell.

This sounds like a good attitude - try to avoid chaining but don’t be too strict about it.

Yes, I agree: The Law of Demeter is debatable, but it tells you to avoid chaining and why. I don’t follow LoD strictly (I simply wouldn’t want to), but as plaatspunt puts it: Chaining is a smell in most cases - it’s just the law part of the name that is misleading - I guess LoD is more like a good advice.