I still get questions, why the hell I'm writing "yet another template engine if PHP is a template language itself". In my opinion, it is not PHP which is so good. The template engines are simply too bad, and unsually offer some control structures taken from PHP, variables, put them into different syntax and that's all. Why the hell someone would like to use such stuff if PHP gives him the same things plus object oriented programming to make the code more reusable. But take a look at another issue. Do you think that imperative languages, like PHP, are comfortable enough to be good languages to write, in fact, simple templates? In my opinion, the language that required to be taught, how to display a nested list and escape script data every time we want it is a mistake in this place. Such languages are created to express fast and advanced algorithms, where we need the full control over the process, not to take some data from the script and put them in a string. Yes, we can modularize them with loads of classes, interfaces etc. but is it still a comfortable way and a good use of OOP? In my opinion - no.

What give us new languages

When people noticed that writing in assembler is too complicated, they invented Fortran and Lisp, the first two high-level programming languages. They allowed to express the same algorithms and calculations in more human-readable form. Later, they invented C and C++, two general-purpose imperative languages. As the WWW appeared on the Internet, another group of people noticed that existing programming languages are too complicated to make dynamic websites. Would you like to deal with memory allocation while writing a CMS? The computers are nowadays faster and faster, and people noticed that sometimes it is much better to use simpler language designed for certain tasks at a cost of performance. In the template engines, the rule is similar. PHP in its current shape was never a good template language, so we try to create something different that simplify this process. And how to achieve this? We have to change the programming paradigm. As we design the new programming language, we can do almost everything with it and add features that are impossible in another language.

OPT template language

The basis of OPT template language is XML. Unlike PHP, OPT understands entire structure of the XHTML code in the templates and checks its syntax before we see something in the browser. All the language constructs are allowed to manipulate the code in the way that is impossible in PHP, using an interface similar to DOM. They can add new attributes, create tags, and the compiler prevents them from generating invalid output. Moreover, I wanted to get rid of programming in the templates, so I designed the control structures in a declarative style. An example of such declarative language is SQL, where you describe, what data you want to have and the database engine decides, how to find them. Here, you simply inform, what you want to see, and the template compiler provides you the implementation. Below, we have an example of displaying a hierarchical list of categories (a category tree):

xml
<opt:tree name="categories">
 	<opt:list><ul><opt:content /></ul></opt:list> <!-- 1 -->
  	<opt:node><li>{$categories.title} <opt:content /></li></opt:node> <!-- 2 -->
  	<opt:treeelse><p>Sorry, there are no categories in the system.</p></opt:treeelse> <!-- 3 -->
</opt:tree>

Do you see here any tree rendering algorithm? We have only elegant definitions, how a flat list looks like (1), how a node looks like (2) what what to show if there are no categories. We even know nothing about the data format. The template would not tell us whether the category tree must be provided as a big object or an array, and what are the details of its structure. As OPT provides a complete declarative programming model, similar solutions can be found almost everywhere in OPT. It really works. A couple of days ago I started writing a small website for my friend. Thanks to OPT, I managed to write all the presentation layer in 15 minutes. The fact that I did not have a working script yet did not concern me. I knew that OPT would do everything for me once I finally decide, where the script would return arrays, where objects, and what they would really be. I do not worry about code refactoring, because the templates remain untouched. Once I make a critical change, I simply recompile the templates and that's all. Try to achieve this in pure PHP or Smarty!

OPT language features:

  1. True XML parser with configurable level of standard-compliance (from strict mode to quirks mode, where everything that is not directly parsed by OPT is a static text).
  2. Variables are data format independent - the data structures are chosen during the compilation thanks to information from the PHP script.
  3. Two complete models of handling modular templates: by including and by template inheritance (also dynamic).
  4. Intuitive support for nested lists
  5. Smart and semi-automatic data escaping.
  6. Additional useful instructions to create cyclically changed values or to add separators between elements.
  7. XML manipulation instructions.
  8. Support for runtime instructions: blocks and components that are designed especially to deal with HTML forms.
  9. Code reusability: write once, use everywhere.
  10. Set of data manipulation and aggregation functions.
  11. Support for i18n.
  12. A complete expression language designed especially for use with XML. It includes the complete PHP object access support.
  13. A basic set of programming structures: conditions and loops, if they are really necessary.

What about the API?

OPT source code design resembles Zend Framework conventions, when it comes to the class/method naming and file structure. It is fully objective - the templates are represented in the script as view objects, where we can assign the script results to and set the data format. Once the view is fed with the data, we create an output object and order to render the view. OPT provides two default views: HTTP and Return. The first one sends the results to the browser and maintains the HTTP headers. The second one returns the generated code back to the script. Of couse everything is extendable: you can write new outputs, define new data formats, write new functions, components and even instructions with the powerful compiler API. The management of all this stuff is also simple, because there is a plugin system.

The templates can be loaded and stored everywhere thanks to PHP streams. All you have to do is to write a new stream wrapper and register it in PHP. The advantage of this solution is that the wrapper can be used with all the file access functions in your script, even with require and include. The output results can be cached, but this time OPT does not provide its own cache handler, allowing the frameworks to do their job. In order to help the programmers manage the templates, the debug console is provided that shows information about the current configuration, executed and compiled templates and the resources used to perform those tasks. The errors are handled with the exceptions and the default error handler provides extra context information with additional explainations, how to fix the problem and where to find the solutions.

Below, you can see a sample use of OPT in the scripts:

php
try
{
	$view = new Opt_View('template_file.tpl');		
	$view->foo = value;
		
	$out = new Opt_Output_Http;
	$out->setContentType(Opt_Output_Http::XHTML, 'utf-8'); // Content negotiation available!
	$out->render($view);
}
catch(Opt_Exception $e)
{
	Opt_Error_Handler($e);
}

However, OPT is not a standalone script. It is the first library in the Open Power Libs series. They share a common core with the basic core that provides the necessary features, like autoloader, configuration, plugin architecture, debugging issues and PHAR support.

Project status

As I mentioned in the excerpt, all the planned features are currently completed, but not fully tested yet. The code seems to work in all the common use cases, but lots of deeper interactions between various elements are a big unknown. At this time we are going to start beta tests that will take some time. Meanwhile, the following tasks are waiting:

  1. To complete the English documentation.
  2. To write the complete unit tests and support for PHAR-s.
  3. To write tutorials, FAQ-s and sample codes for OPT.
  4. To provide the initial add-ons: Unicode function set for the templates, complex port to Zend Framework and probably Kohana. In the near future we are going to provide the support for Symfony, too.

Moreover, the next OPL projects are going to be opened. Currently, we have already started works on Open Power Classes, a set of small PHP classes to deal with various useful stuff. Our next big goal is Open Power Forms - a complete form handling solution for your script that shows the real power of Open Power Template.

How to help?

In the next few days, OPT 2.0.0-dev8 should appear. The source code for this version is already available in SVN, but I want to finish some API reference translations. Test it and send us you opinions. If you think you found a bug, use the bugtracker and let us know about it. Do not be afraid to ask - our community is still quite small, but the Invenzzia team is very helpful and does its best to help you deal with the coding problems.

To sum up

I know this post is full of propaganda stuff, but on this blog, it has not been announced so far and I think it is necessary to show, what this project really is and why we are writing it. Open Power Template is something more that just a template engine - it is probably the first presentation layer framework designed as a complex solution, and in addition - fast. I hope you'll enjoy it. Many people managed to enjoy OPT 1.1.x, and incoming 2.0.0 is simply much better.

Update: OPT 2.0.0-dev8 is available to download. The English manual can be found here.