The first development release of Savant version 3 is ready for download. (Savant is a template system for PHP that uses PHP itself as the template markup language; it supports plugins and output filters, as well as optional compilers.) The following is a link to the PEAR package tarball.

The release rate for Savant has been very high (three major versions in 18 months). This is because had the bad luck (or poor foresight) to start Savant2 on the cusp of the PHP5 release, so it had to handle both PHP4 and PHP5. With any luck, Savant3 should be the last major version number until PHP6.

Some change notes follow, but they are not a replacement for examining the source code. As development progresses, I'll write up real documentation.


Savant2 code was 31793 bytes with comments; Savant3 is 23728 bytes with comments. This is not due to reduced comments. ;-)

PHP5 only, uses public/protected (no private because we want to allow extension) and runs clean under E_ALL|E_STRICT error reporting.

Real unit tests using the .phpt framework. The 'form' plugin test fails becuase the test is not complete yet, but all others pass.

Reduced number of default plugins, mostly from the form element suite. The plugin 'modify' has been renamed to 'safe' but I'm not sure that will remain the case.

In Savant2, you were not supposed to assign a variable with a name starting in "_". In Savant3, there no more restrictions on what you can name an assigned variable; any allowed PHP name is OK.

In Savant2, configuration properties were prefixed with underscore. In Savant3, config properties are stored as a static array inside the conf() method. This has the benefit of keeping all configs away from the assigned variable space (i.e., the object properties). Access only through public getters and setters (which are nominally dumb, but in this case are necessary).

The assign() and assignRef() methods work just like always, but return true/false instead of error objects.

Variable extraction is still allowed. Initially I disliked the idea, but the new configuration scheme allows a very simple and elegant extraction using extract() and get_object_vars($this).

Restricted directories are always on (i.e., Savant2::setRestrict(true) is always the case).

Filters are now simply callbacks; you can specify a function, static class method, or object instance method. The callback should take one parameter, the buffered template output.

Filters are now applied through the native PHP ob_start() callback system, so you can do more complex stuff like ob_gzhandler. However, it makes filters harder to debug, as they occur within the ob_start() process.

Compilers are now simply callbacks; you can specify a function, static class method, or object instance method. The callback should take two parameters, the path to the source template and a reference to the calling Savant object.

No more methods like clear() or getVars(); you can access all assigned variables as public properties of the template object.

No more loading or unloading of plugins or filters; all happens automatically. Once a plugin is instantiated, you cannot un-instantiate it.

Plugins always get a reference to the calling Savant object, just like in Savant1.

Plugin classes must use the method name as their "main" method instead of plugin(). E.g., the 'form' plugin uses form() instead of plugin() as the main method. This is because E_STRICT forces you to have the exact same number of parameters when extending a class.

Plugins are activated via the magic method __call(); thus, no more plugin() method per se. Plugin instance are stored in a static array inside __call(); they are not available to the rest of the object.

All plugins return instead of echo; to display plugin output, use "echo $this->pluginName()". This is because of magic method __toString() requirements. Thus, no more splugin() method.

You can call display() and fetch() the way you did in Savant2, but you can also "echo $Savant;" as the equivalent of display().

The following old methods are rougly congruent to these new method names (this is only a partial list).

    Savant2::loadTemplate() ~= Savant3::template()
    Savant2::setError()     ~= Savant3::setErrorType()
    Savant2::loadPlugin()   ~= Savant3::setPluginConf()
    Savant2::loadFilter()   ~= Savant3::addFilters()
    Savant2::plugin('xxxx') ~= Savant3::xxxx()
Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving you codebase, all while keeping it running the whole time.