Blog posts tagged "smarty"

Simple Object Access from Smarty

August 5th, 2004

On one hand it’s kind of disheartening how much resistance and fear there is towards objects from segments of the PHP community. (hilighted by the recent hostility towards PHP5’s adding of something resembling a working object model) On the other hand can you blame them when popular tools like Smarty punish you for using object?

Transparent, Unified Access

In the ideal world you could pass an array or an object to Smarty and have the access be transparent. Being able to call methods on objects from your template is immensley useful. Besides reinforcing your data model you also:
  1. don’t have to write all those toArray() method to dump your data to Smarty
  2. can lazy load data as needed
  3. can provide intelligent formatting without the need to write a Smarty plugin
And being able to do it transparently means it is painless to migrate from using arrays to using objects (e.g. as your traffic grows, you switch to lazy loading objects), or from objects to arrays. (another way to say it is, having to know the underlying data storage implementation is a clear case of a leaky abstraction)

(fyi this “ideal world” is also known as Template Toolkit)

SPL

There is however a way, with a little effort, to achieve this behaviour with Smarty and PHP5. One of the most useful, and least discussed new features of PHP5, is the SPL, “a collection of interfaces and classes that are meant to solve standard problems”, including allowing objects to behave like arrays, using the ArrayAccess interface.

A quick example (there are probably better ones)

Say you had a class that you used to help you page through a list of results, and at the bottom of each page you wanted to add a slug like “Widgets 21-30 of 142”.

One solution would be to assign {$objectType}, {$showingMin}, {$showingMax}, {$totalToShow} (or some such) variables to Smarty, and then have something like the following in your template:

{$objectType} {$showingMin}-{$showingMax} of {$totalToShow} in

But to my eye that seems to clutter up the paging code with assigns, and clutter up the templates with unintuitive markup. (and this is a simple case)

Another solution would be to build the string at some point in your code, and pass that to Smarty (making your eventual I18N process just that much more challenging)

The third solution is to have your Pager class pretend to be an array, allowing you to add {$page.showStatus} to your templates which Smarty will compile into $this->tplvars['page']['showStatus'], and the SPL will intercept and transform into $page->offsetGet('showStatus');

So whats does the Pager class look like? Well the relevant bits look like:

class Pager implements ArrayAccess {
   ...
   function offsetGet($k) {
    if ($this->offsetExists($k)) {
                return $this->$k();
        }
   }

function offsetExists($k) { return method_exists($this, $k); }

/* set and unset don't do anything */
function offsetSet($k, $v) {} function offsetUnset($k) {}

function showStatus() { ...construct status string and return it.... } }

The offsetGet() method is the intersting piece. It says, “take the array access key, and call the method of the same name on that object”. Voila, you can now pass objects to templates, and call methods on them.

A Word About Security

Generally you trust your template editors, but if calling arbitrary code worries you there are a couple of things you can do.
  • strip all non-word characters from your access key like so: $key = preg_replace('/\W/', '', $key);
  • the method calls are already namespaced to the object, but you could quarantine them further by appending a string to them (e.g. ‘tmpl‘), in which case your offsetGet() becomes
       function offsetGet($k) {
            $k = pregreplace('/\W/', '', $k);
        $f = "tmpl$f";
            return $this->$f();
       }
    
    (alternately you could use Relection API to limit offsetGet to only exposing methods inherited from some base class, or whatever other creative solution strikes your fancy)

(Note most of this code was sketched out on my way home tonight, and my spiral bound notebook’s PHP syntax hilighting is pretty weak not to mention lacks PHP5 support, so there might be some bugs in the above code)

Smarty and Iterators

Okay, so all that above is about using SPL’s array interface to allow method access, but what if you want pass iterators to Smarty? Should just work right? Unfortunately not. You see in Smarty’s
compileforeachstart, arrays are accessed with an explicit array cast, making it impossible to use an iterator. The quick and dirty solution is to remove this explicit cast. However Smarty’s vmethod’s list .first, and .last won’t be available. For that you need this patch sent to the Smarty Dev list. (hasn’t tested it yet)

Tagged: Uncategorized , , , ,

MagpieRSS 0.4

January 20th, 2003

Slouching towards release, part 2

Also, I released MagpieRSS 0.4 today.
  • New and better error handling. Its not very PHP like, but its rationale, and flexible, and designed to be used as part of a larger application. (like I said, not very PHP like)
  • more and better examples on how to use Magpie, including how to use it with Smarty
  • Ships with a custom Smarty plugin for parsing RSS dates so you can include in your templates the nifty construct:
    $item.dc.date|rss_date_parse|date_format:"%A, %B %e, %Y"}
Download Mapie 0.4.

Tagged: Uncategorized ,

Domain Specific Templates

December 22nd, 2002

Rasterweb, whilst musing on PHP and Perl asked:

I think the biggest strength of a system like Movable Type is that the templating system is so powerful and easy to use. Is there any PHP based CMS/weblogging tool that uses templates in a way even close to how Movable Type does?

To which aaron responded:

php does have a decent template system called ‘Smarty’

And I’ll be the first to step up and agree, Smarty is a fine tool, it lacks the amazing flexibility and elegance of Template Toolkit, but thats frosting, and it stacks up nicely compared to Velocity and Cheetah. (more on this theme)

That said, its nothing remotely like Moveable Type’s template system, which I find novel and nearly perfect. As a programmer, with Template Toolkit at my fingers, I tend to think of a template as procedural language for describing presentation. This is the same idea behind PHP and JSP.

MT does something totally different, it defines a domain specific templating language for laying out a blog. I’ve read about domain specific languages in school, but its not until seeing both how elegant, and powerful it can be did I finally understand the appeal. (I’m still not willing to concede the point that Haskell is just plain weird) This is the same idea as JSP’s Taglibs, but without the ugly syntax.

I occasionally run into the limits MT’s language, wishing I had a more flexible conditional, or not operator, but it makes more sense then any approach I’ve seen, and I’m trying to incorporate it into the Protest.net rewrite.

ps. PHP does have ImageMagick bindings, check out the new PHP Imagemagick extension.