June 22, 2007

There’s an interesting aspect about using functions within partials, which I’ve written about before – the existence of functions and the dangers of redeclaring them.

The problem here is using partial-specific functions within partials. We’ve had an instance where we needed a function to solve a recursive problem when displaying data within the partial (a complex tree structure).

The quick’n'dirty solution was to declare the function within the partial, which solves the problem. There was no PHP fatal error right up until functional testing. The reason why this error wasn’t spotted before was because the partial was used only once (if it was ever used within a view), thus never realising itself.

When running functional tests, sfTestBrowser instantiates an instance of the sfContext class and runs the application within a single runtime, which means that all registered global functions exist at all times. And because the partial is used by many views, the second the test encountered the second view that used the aforementioned partial, the test died with a PHP fatal error.

As mentioned in the article from before, the solution is to never declare any functions within template PHP files. Any functions that you need (even if it’s used by a single template file) should be declared within a helper and included appropriately. This way, Symfony guarantees the helper will be included exactly once, avoiding the fatal error that would otherwise crash the application.

June 13, 2007

Well, I’ve written up a short summary of ideas relating to handling Javascript files in relation to requests, not it’s time to evaluate them.

First thing I’ve noticed with the different ways of injecting Javascript into the response is the order by which the files are loaded, the problem being dependency. If you’re using a library such as jQuery (or any other for that matter), the order by which the JS files are loaded is crucial. I usually force jQuery to use the noConflict mode by calling jQuery.noConflict() in a separate file (to keep the original library file intact in case of upgrades and updates) and loading it after jQuery. That’s done in the general view.yml file on the app-level configuration.

But when I try to add an action-specific JS to the mix, things start getting hairy – when you call $this-&gt;getResponse()-&gt;addJavascript(), it adds Javascripts to the beginning of the list of JS files, before the view.yml gets a chance to add its own. In this case, you’re limited to adding JS files via a module-level view.yml file by specifying the view to which you want to append the JS.

This is different when handling components – imagine having, say, a countdown timer written in Javascript. If you’d like to include it in several places but don’t want to handle the dependencies, then there’s a foolproof way of handling those – simply include the dependencies using $this-&gt;getResponse()-&gt;addJavascript(). This time, the components get rendered AFTER the main view, so including JS files this time adds them to the end of the list, after the main view’s files have been added.

The good thing about the latter is that you never have to worry about changing any view.yml files after including the component anywhere in your main views. That lends itself to building self-contained, no-fuss plugins using components, which, in the context of this article, could be HTML widgets, like calendars, calculators, AJAX comment boxes, shoutboxes, etc.