Menu

Tree [r1] /
 History

HTTPS access


File Date Author Commit
 apidoc 2010-03-28 aii [r1]
 lib 2010-03-28 aii [r1]
 sample 2010-03-28 aii [r1]
 test 2010-03-28 aii [r1]
 CHANGES 2010-03-28 aii [r1]
 INSTALL 2010-03-28 aii [r1]
 LICENSE 2010-03-28 aii [r1]
 README 2010-03-28 aii [r1]
 README.html 2010-03-28 aii [r1]

Read Me

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>PHP/Toolbox#2</TITLE>
<style type="text/css">
<!--
dir {  background-color: #EEEEEE}
-->
</style>
</HEAD>
<BODY bgcolor="#ffffff">
<h1><FONT FACE="Arial">PHP/Toolbox#2 </FONT></h1>
<h2 ALIGN="JUSTIFY"><FONT FACE="Arial">What&#146;s new?</FONT></h2>
<P ALIGN="JUSTIFY">The most important thing, new in Second Edition (#2) is <B>RETRO</B><SUP>®</SUP>&#151;
	PHP/Toolbox proprietary template processing technology. All related snippets
	are made to use it to generate HTML contents. So, a new core snippet, <FONT FACE="Courier New">CRenderer,</FONT>
	is included, and a few new features are added to existing #1 snippets as well.
	See CHANGES for more details.</P>
<P ALIGN="JUSTIFY"><I>Note that due to these changes #2 is not 100%-compatible
	with #1; the latter should not be treated as obsolete or deprecated though:
	it&#146;s still supported and will be maintained but, probably, will not be further
	developed.</I></P>
<h2 ALIGN="JUSTIFY"><FONT FACE="Arial"><a name="RETRO">Why RETRO</a><SUP>®</SUP>?</FONT></h2>
<P ALIGN="JUSTIFY">One of the important problems in the web application development
	is a complexity of the mixed HTML and program codes that increase as a power
	of complexity of application. So, a well-known paradigm of separation the
	program from HTML and template-based generation of the resulting HTML document
	is reasonably recognized as a very important or even central feature of web-application
	development toolbox.</P>
<P ALIGN="JUSTIFY">The PHP/Toolbox#1 is still quite useful to embed generated
	snippets into existing HTML code. The <FONT FACE="Courier New">/test</FONT>
	code examples or <FONT FACE="Courier New">/samples</FONT> applications demonstrates
	this approach quite clearly. For example, it&#146;s a usual practice to construct
	the snippet, say, table or menu, include HTML template and then just render
	the snippet where needed:</P>
<DIR>
	<P><FONT FACE="Courier New">&lt;?php<BR>
		$menu = new CTTextMenu(&#133;);<BR>
		include (&#147;sample.html&#148;);<BR>
		?&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">While sample.html is:</P>
<DIR>
	<P><FONT FACE="Courier New">&lt;html&gt;<BR>
		&lt;body&gt;<BR>
		&lt;table&gt;&lt;tr&gt;<BR>
		<B>&lt;?php $menu-&gt;render() ?&gt;<BR>
		</B>&lt;/tr&gt;&lt;/table&gt;<BR>
		&lt;/body&gt;<BR>
		&lt;/html&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">Again, this approach is quite useful, because it often requires
	only a single line of the code to be inserted into HTML template. Moreover,
	your web-designer can easily edit this template with his preferred HTML editor,
	even WYSIWYG one.</P>
<P ALIGN="JUSTIFY">However, such a technique allows you to easily handle HTML
	&#145;frame&#146; around snippet, but not the codes that the snippet itself generates.
	The problem of the snippet design customization can be partly solved by providing
	the CSS styles to any generated HTML elements, so that almost any attributes
	of their visual representation can be controlled; meanwhile, their <I>structure</I>
	cannot. The latter is possible only by subclassing the snippet and change
	its default behavior as one needs; however, it definitely requires the <I>manual
	</I>coding of the HTML generation within miscellaneous subclass methods.</P>
<P ALIGN="JUSTIFY">From this point of view, it&#146;s probably would be quite convinient
	to provide the template for each snippet <I>itself</I> as well as we provide
	it for the whole page, for instance. Well, there are a lot of PHP template
	engines, more or less powerful, that can be possibly used for this purpose.
	However, they are all based on the common principle&nbsp;&#151; a template file
	with some text &#145;macros&#146; is read, line by line, and these macros are expanded
	by template engine <I>written in PHP. </i></P>
<P ALIGN="JUSTIFY">Ok, this is just fine but let&#146;s remember that PHP <I>itself</I>
	is actually a sort of &#145;template engine&#146;, just because it allows (and even
	<I>requires</I>) to embed the PHP codes into HTML source. So, what we really
	get is a template engine built over another template engine! Sounds a bit
	cumbersome? Really, is it <I>efficient</I>? If we are already basing our development
	on a rather good and powerful &#145;template&#146; mechanism, what do we need another
	for? </P>
<P ALIGN="JUSTIFY">In short, I decided to see, is another solution possible? The
	answer is probably &#145;yes&#146; and it&#146;s rather obvious &#151; a simple<FONT FACE="Courier New">
	include()</FONT> statement manages its work just fine. Really, why <FONT FACE="Courier New">&lt;?php
	print($VARIABLE)?&gt;</FONT> is much worse than, say, <FONT FACE="Courier New">{VARIABLE}</FONT>?
	Simply a bit longer? Then, what about <FONT FACE="Courier New">&lt;?php while($CONDITION):?&gt;</FONT>
	against something like <FONT FACE="Courier New">&lt;!-- BEGIN CONDITION_loop
	--&gt;</FONT>? Frankly, I can&#146;t find a great difference&#133;</P>
<P ALIGN="JUSTIFY">On the other hand, it&#146;s not absolutely clear, <I>how</I> we
	can utilize this mechanism for our purposes. In particular, how to force it
	to co-operate with OOP-based Tbox snippets nature?</P>
<P ALIGN="JUSTIFY">Fortunately, the PHP development team in its wisdom gives us
	such an opportunity. The point is that <FONT FACE="Courier New">include()
	</FONT>statement can happen anywhere in the PHP program code, even inside
	the function. This means that (beside other things) it should operate in <I>local
	context</I> of that function. This way, we can easily provide co-operation
	between the snippet&#146;s methods and implementing templates with namespace isolation!</P>
<P ALIGN="JUSTIFY">So, &#145;<B>RETRO</B>&#146; stands for &#145;<B>R</B>eally <B>E</B>fficient
	<B>T</B>emplate <B>R</B>endering <B>O</B>perations&#146;. Note, I didn&#146;t say <I>Fast</I>,
	but <I>Efficient</I> instead. Why? Just because there is at least one really
	<I>fast</I> rendering method using something like <FONT FACE="Courier New">str_replace()</FONT>
	function. However, is it really <I>efficient</I>? I&#146;m afraid not: while it
	allows fast substitution of variable references, it doesn&#146;t allow branching,
	looping, etc at all. At the same time, usual PHP template engines that make
	the latter possible are rather complex and large to be compiled and executed
	quickly; in any case things should go harder than PHP input scan itself!</P>
<h2 ALIGN="JUSTIFY"><FONT FACE="Arial">Using RETRO<SUP>®</sup></FONT></h2>
<P ALIGN="JUSTIFY">The heart of <B>RETRO</B> technology is <FONT FACE="Courier New">CRenderer
	</FONT>snippet. It&#146;s documented quite well in <FONT FACE="Courier New">/apidoc,
	</FONT>so we just observe its main programming patterns below.</P>
<P ALIGN="JUSTIFY">The renderer is isolated from the conventional snippets to
	provide an opportunity to specify some common rendering details in one place.
	Next, as its usual clients are snippet objects, it supports the features for
	that foremost. </P>
<h3 ALIGN="JUSTIFY"><FONT FACE="Arial">Example 1</FONT></h3>
<DIR><FONT FACE="Arial"> </font>
	<P><FONT FACE="Courier New">&lt;?php<BR>
		$test_object-&gt;class = &#147;test-object&#148;;<BR>
		$test_object-&gt;TITLE = &#147;The Test&#148;;<BR>
		$test_object-&gt;BODY = &#147;The quick brown fox jumps over the lazy dog&#148;;<BR>
		<BR>
		$r = CRenderer();<BR>
		$r-&gt;render($test_object);<BR>
		?&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">The template file should be located at <FONT FACE="Courier New">html/test-object.html:</font></P>
<DIR>
	<P><font face="Courier New, Courier, mono">&lt;html&gt;<BR>
		&lt;head&gt;<BR>
		&lt;title&gt;&lt;?=$THE-&gt;TITLE?&gt;&lt;/title&gt;<BR>
		&lt;/head&gt;<BR>
		&lt;body&gt;<BR>
		&lt;h1&gt;&lt;?=$THE-&gt;TITLE?&gt;&lt;/h1&gt;<BR>
		&lt;p&gt;&lt;?=$THE-&gt;BODY?&gt;&lt;/p&gt;<BR>
		&lt;/body&gt;<BR>
		&lt;/html&gt;</font></P>
</DIR>
<P ALIGN="JUSTIFY">Note that:</P>
<UL>
	<P ALIGN="JUSTIFY">
	<P ALIGN="JUSTIFY">
	<LI>You can often use &#145;short&#146; PHP syntax that is even more compact;</LI>
	<p></P>
	<P ALIGN="JUSTIFY">
	<P ALIGN="JUSTIFY">
	<LI>All variable references are <I>local</I>; you should use <FONT FACE="Courier New">global</FONT>
		directive to access global namespace;</LI>
	<p></P>
	<P ALIGN="JUSTIFY">
	<P ALIGN="JUSTIFY">
	<LI>&#145;<FONT FACE="Courier New">$THE</FONT>&#146; variable is used to refer to the
		rendered entity; it often improves readability as well;</LI>
	<p></P>
	<P ALIGN="JUSTIFY">
	<P ALIGN="JUSTIFY">
	<LI>Default template location is &#145;<FONT FACE="Courier New">html</FONT>&#146; directory
		and default extension is &#145;<FONT FACE="Courier New">.html</FONT>&#146;; </LI>
	<p></P>
	<P ALIGN="JUSTIFY">
	<P ALIGN="JUSTIFY">
	<LI>By default, <FONT FACE="Courier New">CRenderer</FONT> uses passed entity&#146;s
		&#145;<FONT FACE="Courier New">class</FONT>&#146; field to locate the template for
		it; if the field does not exist or entity is not an object then &#145;<FONT FACE="Courier New">default</FONT>&#146;
		template is used;</LI>
	<p></P>
	<P ALIGN="JUSTIFY">
	<P ALIGN="JUSTIFY">
	<LI>All defaults can surely be overridden.</LI>
	<p></P>
</UL>
<h3 ALIGN="JUSTIFY"><FONT FACE="Arial">Example 2</FONT></h3>
<P ALIGN="JUSTIFY">The <FONT FACE="Courier New">CRenderer&#146;s render()</FONT> method
	can also accept the <FONT FACE="Courier New">array</FONT> of entities:</P>
<DIR>
	<P><FONT FACE="Courier New">&lt;?php<BR>
		$test_object_1-&gt;class = &#147;test-object&#148;;<BR>
		&#133;<br>
		</FONT><FONT FACE="Courier New"> $r = CRenderer();<BR>
		$r-&gt;render(array($test_object_1, &#133;));<BR>
		?&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">The template below produces a list of partial headers followed
	by paragraph texts:</P>
<DIR>
	<P><FONT FACE="Courier New">&lt;h1&gt;&lt;?=$THE_KEY?&gt;: &lt;?=$THE-&gt;TITLE&lt;/h1&gt;<BR>
		&lt;p&gt;&lt;?=$THE-&gt;BODY?&gt;&lt;/p&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">Looks like not very useful? Well, how about the following?</P>
<h3 ALIGN="JUSTIFY"><FONT FACE="Arial">Example 3</FONT></h3>
<DIR><FONT FACE="Arial"> </font>
	<p><FONT FACE="Courier New">&lt;?php<BR>
		$r = CRenderer();<BR>
		$r-&gt;render(do_query(<br>
		</FONT><FONT FACE="Courier New">&#147;select &#146;test-object&#146; as
		class, TITLE, BODY from para&#148;<br>
		</FONT><FONT FACE="Courier New">)</FONT><FONT FACE="Courier New">);<BR>
		?&gt;</FONT></p>
</DIR>
<P ALIGN="JUSTIFY">The <FONT FACE="Courier New">render()</FONT> method can also
	accept the PHP resource #, so template file like above produces formatted
	content of a whole table from database!</P>
<h3 ALIGN="JUSTIFY"><FONT FACE="Arial">Example 4</FONT></h3>
<P ALIGN="JUSTIFY">At last, you can render simple scalar variable as well as an
	object: given the script from the 1<SUP>st</SUP> example, template file located
	at <FONT FACE="Courier New">html/test-object.html</FONT>, would contain:</P>
<DIR>
	<P><FONT FACE="Courier New">&lt;html&gt;<BR>
		&lt;head&gt;<BR>
		&lt;title&gt;&lt;?=$THE-&gt;TITLE?&gt;::&lt;?=$THE_KEY?&gt;&lt;/title&gt;<BR>
		&lt;/head&gt;<BR>
		&lt;body&gt;<BR>
		&lt;h1&gt;&lt;?=$THE-&gt;TITLE?&gt;&lt;/h1&gt;<BR>
		&lt;?$this-&gt;render($THE-&gt;BODY, &#147;test-body&#148;)?&gt;<BR>
		&lt;/body&gt;<BR>
		&lt;/html&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">and sub-template <FONT FACE="Courier New">html/test-body.html</FONT>
	would be like this:</P>
<DIR>
	<P><FONT FACE="Courier New">&lt;p&gt;&lt;?=THE?&gt;&lt;/p&gt;</FONT></P>
</DIR>
<P ALIGN="JUSTIFY">This way, it&#146;s possible to control sub-templates flexibly.</P>
<h2 ALIGN="JUSTIFY"><FONT FACE="Arial">Pros &amp; Contras of #2</FONT></h2>
<P ALIGN="JUSTIFY">The main difference of #2 and #1 branches is almost completely
	hidden from a common user. They both have all workhorse snippets pre-cooked;
	their overall throughputs are almost the same. At the same time #2 is much
	more flexible and might be more complex to dig in. On the other hand, it allows
	to customize the HTML ouput much more easily: it means, say, that it provides
	much more powerful theming support. </P>
<hr>
<small><address>
(C) Alexey Ilyin &lt;<a href="mailto:ai@a4web.com">ai@a4web.com</a>&gt;, 2001.<br>
Home page: <a href="http://alexworld.a4web.com">alexworld.a4web.com</a>
</address></small>
</BODY>
</HTML>