Symfony Templates and Ruby’s ERb

  • Posted by Mike Naberezny in PHP,Ruby

    After hearing the podcast, I went over to the Symfony website to check it out. I haven’t downloaded Symfony yet but I did watch this screencast. One thing that I think Symfony gets right is that it appears to use partitioned PHP code for its templates, in the spirit of Paul‘s Savant system. Putting all the “Smarty vs. Savant”-type arguments aside, the resulting templates in Symfony are nice and look very much like ERb (.rhtml) as it is used by Ruby-on-Rails. I think the ERb templates are a bit cleaner. However, it doesn’t have to stay that way.

    In Ruby, instance variables are accessed with @var_name. This is the same as self.var_name in Python or $this->var_name in PHP. If the template’s variables are scoped as instance variables of a class such as in Savant, and short_open_tag is disabled, the resulting PHP syntax can be a bit unwieldy:

    var_name ?>
    

    Compare this to the succinct but equally powerful ERb:

    <%= @var_name %>
    

    I noticed in the Symfony demo that there is no separation of scope between variables passed to the template from the controller and local variables in the template. In the screencast, $products in the template comes from the controller and is indistinguishable from the local variables $id and $title. I’d like to see them scoped properly ($this->products) but I can certainly understand why they did it this way. Using $this-> in the template everywhere quickly gets messy.

    One solution to this problem is to enable short_open_tags and then give the nod to Ruby by overloading PHP’s silence operator (@) to $this-> in the templates. This gives a very similar syntax to ERb:

    
    

    Using the silence operator in this way won’t break syntax highlighting in the IDEs, since this is legal PHP syntax on its own. The silence operator would not normally prefix a dollar sign, so keeping the dollar allows us to distinguish between normal code that should be silenced and when the operator is overloaded to $this->. Templates should never be doing operations that need to be silenced anyway.

    The syntax shown above is much shorter and more convenient but there appear to be two problems with this solution. First, relying on short_open_tag is a beginner’s mistake in PHP since it’s not enabled on all installations. Second, it’s not practical on most installations to install an extension to do this overloading.

    Fortunately, there is an easy solution to both of these problems. At some point, the template engine must include() the templates for PHP to execute them. A stream wrapper can be registered to rewrite the @$ into $this-> and also expand short tags if short_open_tag is not enabled. The result is a short snippet of pure PHP code that gives this syntax and should also run on the majority of installations.

    Here’s the proof of concept (PHP 5).