Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

The HYSOCAMTT templating approach

DZone's Guide to

The HYSOCAMTT templating approach

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

This article aims to highlight a approach which allows one to separate everything from one's business logic to one's design logic, to XHTML from CSS, one's Javascript from the page structure, etc., while at the same time being able to be lazy and include, for example, CSS information within the same document (template) as one's XHTML. The script can also be used for more advanced XML-related features which I won't go into here. This article assumes some familiarity with Smarty, or at least the concept of templating.

By: Brett Zamir

First a quick disclaimer: While the discussion revolves around this open-source Smarty extension class (called SmartyDocB, with documentation), the approach could be applied to templating based on other PHP-specific templating systems, in XSL, etc. However, I don't have a lot of time now to maintain the code for what I describe below (though I'm happy to try to answer questions if I can), but I feel that the code itself is sufficiently mature, and if nothing else, that its approach to templating is perhaps unique, so in the event that it could be useful for others, I am drawing your attention to it. Perhaps, if there is interest, I may be able to revisit the code at a later date.

I'll begin with some examples with the templates and give you a quick impression of how this could be used and useful, then go into the specifics of setup, and finally discuss some future goals for the project. I'll conclude with a discussion of the use of XSL or XQuery for templating and issues of porting one's templates to use with other programming languages.

Why and How to Use This Templating Approach
An Introduction to The HYSOCAMTT approach "Have-Your-Separation-Of-Concerns-And-Mix-Them-Too")

I don't know about you, but when everyone is suggesting external stylesheets over the <style> tag and the W3C deprecated even the @style attribute (which was itself an enabler of the deprecating of previous HTML tags used for formatting), I was unhappy. Not because I didn't see the wisdom of separating structure from styling—but because it meant I could no longer be lazy—or actually, something which is often equivalent—I couldn't be as efficient. I'd have to actually open up another file, lose my concentration (my short-term memory is deplorable), duplicate work by finding some means of referencing the structural tag so that the external style information can be applied to it, and then hope that by looking at the structural code in the future without styling cues around it, I'd be able to tell from my class names, to what part of the page the structural code was referring.

For example, while in plain old-style HTML, to make some paragraph small, I could get by with:

<p><small>This website is run by an individual......</small></p>


For handling separation of styles, I'd have to:

  1. Start with: <p>This website is run by an individual......</p>
  2. Add a class or id (for referencing), so that I didn't make all of my paragraphs small, and according to good practice, come up with a semantic rather than styling name: <p class="disclaimer">This website is run by an individual...</p>
  3. Then open up and save a new stylesheet file, taking into account a good file location so that moving the file contents wouldn't break the association, and then add an appropriate <link> (or <?xml-stylesheet...?> if only IE would start supporting it) in the head of my XHTML document to refer back to the stylesheet.
  4. Add the style declaration, including the full property name (here "font-size") in question, to the stylesheet: p.disclaimer {font-size: small;}
  5. Refresh my XHTML to make sure that it works.

And then, in the future, if I looked over my template (or file), I might forget how I styled the disclaimer, and if I wanted to change it, I'd have to open up the stylesheet file if it wasn't open, and search to find that style declaration. Or, if I were looking at the stylesheet, I might not remember all the files in which I used the disclaimer, so I'd have to open all of my files up to check to see whether any proposed style change in the stylesheet would be suitable everywhere.

Again, there are a whole lot of benefits to separating styles such as greater accessibility, faster downloads, etc., which you can read about in many other articles, but you can see (as you may well know already) how cumbersome the above can be (especially if you're averse to most IDEs like I am).

Imagine, however, if you could do the following within your template:

    {moveto target=css}
p.disclaimer {font-size:small;}
{/moveto}

<p class="disclaimer">This website is run by an individual......</p>


And have a script extract the "moveto" contents into a separate site-wide file (site-wide because this speeds up downloads by taking advantage of caching that occurs when the same stylesheet is encountered by a browser on a subsequent visit to the same or another page of the site that includes it). This is exactly what SmartyDocB does. Moreover, it will put comments within the CSS file which indicate from which template the above style originated. So if the above template file was called, footer.tpl, within the site-side CSS file (which could include other auto-generated or manually edited CSS content), the following would be added at the top of the file (to the top to ensure that the developer was aware during testing that subsequent (preexisting) styles weren't superceding the newly added ones:

    /* Begin moveto footer.tpl */
p.disclaimer {font-size:small;}
/* footer.tpl end moveto */


An even more succinct option in SmartyDocB is to use a special syntax to avoid the duplication (of the element and class-name) present above:

    <<p eclcss="font-size:small;">>This website is run by an individual......<</p>


What this will do is extract the style information to be added to an external CSS file (removing it from the resulting XHTML structural output), and targeted according to the current element ('e') and its class ('cl'), thus "eclcss", thereby reproducing the same exact effect as above. Similar attribute exist for targeting to the tag in the <head> (useful for testing), or to specify the class by a pseudo-class, by the current element's id, etc.

Notice that the automated CSS file-writing implied by the above can be turned off via the script (certainly recommended for live sites where you do not want each visit to your site to cause the rewrite of a CSS file!), and optionally be accessible (especially during debugging) via a GET call. For example, if file-writing is turned off, you can still optionally allow, via the script, the appending of something like "?rewrite=1" (if you have this option turned on) in order to force say the rewriting of the {moveto} contents (in such a case, the CSS file writing portion would not take place otherwise, and the {moveto} contents and any changes therein would thus be ignored until the next rewrite). The rewriting only takes place within the commented blocks, so if you manually edit the file, any portions outside of the commented blocks should not be overwritten.

Thus, we have the advantage that our resultant code is nice and clean (and allows site-wide styles to be manipulated all at once, if desired), while we can still be "messy" by writing our styles with our structural content together, or as I prefer to consider it, we can still be more efficient and intuitive in allowing our styles to be contained, alongside the places where we are most likely to associate them. And we can always look at the resulting stylesheet file to find out from which template a style originated, if we forgot (or we can move the styles later out of our template file, if we feel that they are more suitably kept in a more generic template file, or just remove the styles from the template and out of the commented block in the stylesheet). This can also benefit designers if they are different from ourselves, as even the style design can be compartmentalized, yet optionally reassembled.

While there isn't an inline equivalent of the above for Javascript event handlers (e.g., to add and onload attribute with content and have it be converted into unobtrusive Javascript within an external Javascript file), there is a means of shuffling away a block of Javascript content (also using {moveto} as described above for styles but setting the target to "code" (pseudonyms like these are used when targeting to external files, while the element names (e.g., script, style, etc.) are used as targets when being sent to the head of the document)), as are methods for shuffling away DTD, W3C Schema, XSL, and even personal note content.

The script also allows targeting to specified files or to the head of the document, and many other features.

Setup

Setting up SmartyDocB is almost identical to the setup for Smarty. The only difference is that you should also include the SmartyDocB class and define a new object based on that for SmartyDocB:

    require($smarty_dir.'/smarty/libs/Smarty.class.php');
require($smarty_dir.'SmartyDoc2.class.php');
$smarty = new Render_SmartyDoc();


You can add use functions (methods) or variables (properties) within your $smarty object in the same way you do with Smarty. For example:

    $smarty->template_dir ='<path to my templates dir>';
$smarty->compile_dir = '<path to my compile dir>';
$smarty->cache_dir = '<path to my cache dir>';
$smarty->config_dir = '<path to my configs dir>';


There will also be other methods and properties available which are specific to SmartyDocB. I won't go into their use here, as there are quite a few (documented, for the most part at the official documentation, if not in the source code). However, I should point out that after assigning variables, the code to display the document in the fashion which utilizes the {moveto} and other SmartyDocB-specific features (such as XHTML content negotiation) is as follows:

    $smarty->displayDoc('mytemplate.tpl');


Notice that when using displayDoc, your template code will generally need to use specialized elements (or rely on the automated features of SmartyDocB to auto-create <html> and <body> tags for example) to create specified elements for the head or footer of the document, since otherwise the script is not able to detect where to place items. For example, you cannot manually create a <style> tag and <head> tag, etc. (unless you use the specialized elements such as {doc_info style="..."} which can be placed anywhere in your templates) and then expect the script to find your manually created elements and insert its automatically created ones. Ideally in the future, the script can be made to detect this, but it does not currently do so. But this is not so difficult to do, and may even save you coding work, as some of these can be intelligently automated by the script.

Future goals

Besides the above-mentioned ideas for auto-created unobtrusive Javascript from inline HTML-like constructs and for auto-detecting existing head content for the targeting of {moveto} injections, one other important feature which I hope to add in the future, is the ability for one to automatically update one's templates if one has made changes within the targeted blocks of a CSS (or Javascript, etc.) file. Currently, if you make changes to the CSS file within the targeted blocks, those could be overwritten by your template which is targeted to that block if you visit a page using that template and you don't have the file-writing turned off, and as there is no automated means to have the edited content reinjected back into the template, you'll currently need to manually update the template file in such a case to reflect the changes.

XSL and Templating

XSL has an advantage over Smarty in that it readily allows for future transformation (e.g., if you wanted your template code to later be updated to XHTML 2.0), but I hope someone might write the equivalent for Smarty syntax in the future. I don't use XSL, even though it is a standard and more portable between languages (see also below), since it is a lot easier to distinguish curly-bracketed variables and functions from the surrounding markup, than it would be to use even more XML tags (processing instructions are a little better, especially if rendered on an IDE which can color-code them differently, but they still use angled brackets and each time they are used, they require an extra character or two to type!; besides, Smarty functions don't require quotation marks, etc.).

Basically, to adapt XSL templates to the above approach, would involve having specific tags or processing instructions (e.g., <moveto> or <?moveto ... ?> ) to be processed by PHP with an XML parser, or perhaps using registerPHPFunctions in the PHP XSL extension).

XQuery and Templating

XQuery is often described as a fun language; it is both intuitive and powerful, for those of us who don't think in terms of relational tables (yet it also allows such things as joins, unions, etc. and even potential interfacing with SQL). Unfortunately, to date, there has been relatively little as far as XQuery available for PHP: one partial yet sadly-apparently-defunct implementation (within PHP XML Classes) and as part of the nice (but large and a little-hard-to-find-shared-hosting-with-support-for) Berkeley DB XML as used with the PHP DBA extension.

XQuery has the potential to be used for templating, and unlike XSL, whose recursive nature can make a procedural programmer dizzy (though XQuery as with XSL is a declarative language), XQuery has at least more of a do-this-then-do-that feel with which I think we PHP programmers can better relate (besides also being somewhat similar to the long-time PHP side-kick, SQL, yet suited to XML and with much more power than SQL, especially for non-predictably structured, document-centric applications (e.g., for working on XHTML, DocBook, or TEI)). In a template context, an XQuery statement or series of statements might be used to draw from specific sources (as {include} does in Smarty, but with specific portions of a document), while optionally surrounding it with static XML.

Besides potentially replacing relational databases (though also implemented in some relational databases) in its implementation in native XML databases, there is even XQuery as a server-side language (see especially the example on page two of the article, whose syntax (used with the eXist native XML database) itself is reminiscent of that used in Smarty). Smarty itself might even leverage this potential and define extension functions which allow processing of XQuery in such a manner.

Incidentally, I've created an extension for Firefox (in beta, so please submit a review if you like it or email me at brettz9 at the site yahoo.com) called XqUSEme which can allow one to harness the open-source Saxon-B XQuery (or a local installation of Berkeley DB XML) to get one's feet wet in performing client-side XQueries (such as on the currently loaded XML document in a Firefox tab or even on a document originally in poorly-formed HTML but turned into a well-formed document by Firefox's internal DOM representation).

Templating across programming languages

There is no standard for templating which works across programming languages (besides the awkward while admittedly powerful XSL). This is unfortunate, I think, given that the purpose of a template is to make an abstraction, and since it is being separated from the business logic anyways, I think it might be nice if one wanted to rewrite the program (e.g., to turn a PHP website into a Firefox extension), to be able to easily port over the template code (and even have a standard API for interfacing with the templates on the business logic side). However, I think there are means around this, as mentioned below.

While PHP wonks may prefer to compare PHP with Java, I tend to compare it with Javascript—both because they are both programming languages for the masses, they are quite helpful if not essential in website design, they are both open source, and they are thankfully both weakly typed languages. (I say thankfully because it at least lowers the barrier to entry, but also makes for rapid application development, and I think greater clarity in code, by the lack of typing everywhere allowing one to focus on the logic; however, I won't extend this unending and unendable debate here any further.) They can even both transcend their specialization (e.g., PHP GTK for client-side use, or Server-side Javascript, as in the Firefox POW extension).

Since these often go together and may be studied by the same people, I think that there is great potential in attempting to make it even more easy for those familiar with one language, to learn the other, including with templating systems.* One class I think may be ripe for such adaptation is Trimpath's Javascript Templates. I believe this could be adapted to follow the Smarty syntax to make it easier for PHP developers to utilize their Smarty knowledge when developing Javascript (such as Firefox) applications.**

I hope this article may have been of some interest and use.

Brett Zamir

* While it may be tempting to think that Javascript (at least "Unobtrusive Javascript" which registers event handlers external to its X/HTML) is inevitably separated from the structure, since it is ideally in its own file, there are still common means, such as when using the DOM, which do build content, and which one may—especially in larger applications, such as those used in building Firefox extensions—wish to instead include along with the static content within the same template(s). (A Javascript templating engine such as Trimpath's still relies on the DOM, but otherwise save the developer from needing to specify his own content mixed in with DOM functions.)

** In the same vein, I might mention that we've set up a Javascript wiki, to allow us to build up libraries of code which can implement PHP functions within Javascript and vice versa (of course, there may be some inconsistencies, but I believe it could greatly assist the memory load to have equivalent functions, especially the intuitive and abundant PHP functions, available in the other language). I guess JsLib has taken this approach already to some extent, but I'd like to see this implemented universally and as close as possible to the actual PHP functions. Any other volunteers?

You are welcome to contact the author at brettz9 at the site yahoo.com with further questions or offers of employment!

Originally published on Zend's DevZone. Used by permission.

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}