mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-04 18:34:27 +02:00
Split up docs.
This commit is contained in:
411
docs/appendixes.sgml
Normal file
411
docs/appendixes.sgml
Normal file
@@ -0,0 +1,411 @@
|
|||||||
|
<part id="appendixes">
|
||||||
|
<title>Appendixes</title>
|
||||||
|
<chapter id="troubleshooting">
|
||||||
|
<title>Troubleshooting</title>
|
||||||
|
<para></para>
|
||||||
|
<sect1>
|
||||||
|
<title>Smarty/PHP errors</title>
|
||||||
|
<para>
|
||||||
|
Smarty can catch many errors such as missing tag attributes
|
||||||
|
or malformed variable names. If this happens, you will see an error
|
||||||
|
similar to the following:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title>Smarty errors</title>
|
||||||
|
<programlisting>
|
||||||
|
Warning: Smarty: [in index.tpl line 4]: syntax error: unknown tag - '%blah'
|
||||||
|
in /path/to/smarty/Smarty.class.php on line 1041
|
||||||
|
|
||||||
|
Fatal error: Smarty: [in index.tpl line 28]: syntax error: missing section name
|
||||||
|
in /path/to/smarty/Smarty.class.php on line 1041</programlisting>
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Smarty shows you the template name, the line number and the error.
|
||||||
|
After that, the error consists of the actual line number in the Smarty
|
||||||
|
class that the error occured.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
There are certain errors that Smarty cannot catch, such as missing
|
||||||
|
close tags. These types of errors usually end up in PHP compile-time
|
||||||
|
parsing errors.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title>PHP parsing errors</title>
|
||||||
|
<programlisting>
|
||||||
|
Parse error: parse error in /path/to/smarty/templates_c/index.tpl.php on line 75</programlisting>
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When you encounter a PHP parsing error, the error line number will
|
||||||
|
correspond to the compiled PHP script, not the template itself. Usually
|
||||||
|
you can look at the template and spot the syntax error. Here are some
|
||||||
|
common things to look for: missing close tags for {if}{/if} or
|
||||||
|
{section}{/section}, or syntax of logic within an {if} tag. If you
|
||||||
|
can't find the error, you might have to open the compiled PHP file and
|
||||||
|
go to the line number to figure out where the corresponding error is in
|
||||||
|
the template.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="tips">
|
||||||
|
<title>Tips & Tricks</title>
|
||||||
|
<para>
|
||||||
|
</para>
|
||||||
|
<sect1>
|
||||||
|
<title>Blank Variable Handling</title>
|
||||||
|
<para>
|
||||||
|
There may be times when you want to print a default value for an empty
|
||||||
|
variable instead of printing nothing, such as printing "&nbsp;" so that
|
||||||
|
table backgrounds work properly. Many would use an {if} statement to
|
||||||
|
handle this, but there is a shorthand way with Smarty, using the
|
||||||
|
<emphasis>default</emphasis> variable modifier.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>Printing &nbsp; when a variable is empty</title>
|
||||||
|
<programlisting>
|
||||||
|
|
||||||
|
{* the long way *}
|
||||||
|
|
||||||
|
{if $title eq ""}
|
||||||
|
&nbsp;
|
||||||
|
{else}
|
||||||
|
{$title}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
{* the short way *}
|
||||||
|
|
||||||
|
{$title|default:"&nbsp;"}</programlisting>
|
||||||
|
</example>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Default Variable Handling</title>
|
||||||
|
<para>
|
||||||
|
If a variable is used frequently throughout your templates, applying
|
||||||
|
the default modifier every time it is mentioned can get a bit ugly. You
|
||||||
|
can remedy this by assigning the variable its default value with the
|
||||||
|
<link linkend="language.functions.assign">assign</link> function.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>Assigning a template variable its default value</title>
|
||||||
|
<programlisting>
|
||||||
|
{* do this somewhere at the top of your template *}
|
||||||
|
{assign var="title" value=$title|default:"no title"}
|
||||||
|
|
||||||
|
{* if $title was empty, it now contains the value "no title" when you print it *}
|
||||||
|
{$title}</programlisting>
|
||||||
|
</example>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Passing variable title to header template</title>
|
||||||
|
<para>
|
||||||
|
When the majority of your templates use the same headers and footers, it
|
||||||
|
is common to split those out into their own templates and include them.
|
||||||
|
But what if the header needs to have a different title, depending on
|
||||||
|
what page you are coming from? You can pass the title to the header when
|
||||||
|
it is included.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>Passing the title variable to the header template</title>
|
||||||
|
<programlisting>
|
||||||
|
|
||||||
|
mainpage.tpl
|
||||||
|
------------
|
||||||
|
|
||||||
|
{include file="header.tpl" title="Main Page"}
|
||||||
|
{* template body goes here *}
|
||||||
|
{include file="footer.tpl"}
|
||||||
|
|
||||||
|
|
||||||
|
archives.tpl
|
||||||
|
------------
|
||||||
|
|
||||||
|
{config_load file="archive_page.conf"}
|
||||||
|
{include file="header.tpl" title=#archivePageTitle#}
|
||||||
|
{* template body goes here *}
|
||||||
|
{include file="footer.tpl"}
|
||||||
|
|
||||||
|
|
||||||
|
header.tpl
|
||||||
|
----------
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>{$title|default:"BC News"}</TITLE>
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
|
||||||
|
|
||||||
|
footer.tpl
|
||||||
|
----------
|
||||||
|
</BODY>
|
||||||
|
</HTML></programlisting>
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
When the main page is drawn, the title of "Main Page" is passed to the
|
||||||
|
header.tpl, and will subsequently be used as the title. When the
|
||||||
|
archives page is drawn, the title will be "Archives". Notice in the
|
||||||
|
archive example, we are using a variable from the archives_page.conf
|
||||||
|
file instead of a hard coded variable. Also notice that "BC News" is
|
||||||
|
printed if the $title variable is not set, using the
|
||||||
|
<emphasis>default</emphasis> variable modifier.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Dates</title>
|
||||||
|
<para>
|
||||||
|
As a rule of thumb, always pass dates to Smarty as timestamps.
|
||||||
|
This allows template designers to use <link
|
||||||
|
linkend="date.format">date_format</link> for full control over date
|
||||||
|
formatting, and also makes it easy to compare dates if necessary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
NOTE: As of Smarty 1.4.0, you can pass dates to Smarty as unix
|
||||||
|
timestamps, mysql timestamps, or any date parsable by strtotime().
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>using date_format</title>
|
||||||
|
<programlisting>
|
||||||
|
{$startDate|date_format}
|
||||||
|
|
||||||
|
OUTPUT:
|
||||||
|
|
||||||
|
Jan 4, 2001
|
||||||
|
|
||||||
|
|
||||||
|
{$startDate|date_format:"%Y/%m/%d"}
|
||||||
|
|
||||||
|
OUTPUT:
|
||||||
|
|
||||||
|
2001/01/04
|
||||||
|
|
||||||
|
|
||||||
|
{if $date1 < $date2}
|
||||||
|
...
|
||||||
|
{/if}</programlisting>
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
When using {html_select_date} in a template, The programmer will most
|
||||||
|
likely want to convert the output from the form back into timestamp
|
||||||
|
format. Here is a function to help you with that.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>converting form date elements back to a timestamp</title>
|
||||||
|
<programlisting>
|
||||||
|
// this assumes your form elements are named
|
||||||
|
// startDate_Day, startDate_Month, startDate_Year
|
||||||
|
|
||||||
|
$startDate = makeTimeStamp($startDate_Year,$startDate_Month,$startDate_Day);
|
||||||
|
|
||||||
|
function makeTimeStamp($year="",$month="",$day="")
|
||||||
|
{
|
||||||
|
if(empty($year))
|
||||||
|
$year = strftime("%Y");
|
||||||
|
if(empty($month))
|
||||||
|
$month = strftime("%m");
|
||||||
|
if(empty($day))
|
||||||
|
$day = strftime("%d");
|
||||||
|
|
||||||
|
return mktime(0,0,0,$month,$day,$year);
|
||||||
|
}</programlisting>
|
||||||
|
</example>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>WAP/WML</title>
|
||||||
|
<para>
|
||||||
|
WAP/WML templates require a php Content-Type header to be passed along
|
||||||
|
with the template. The easist way to do this would be to write a custom
|
||||||
|
function that prints the header. If you are using caching, that won't
|
||||||
|
work so we'll do it using the insert tag (remember insert tags are not
|
||||||
|
cached!) Be sure that there is nothing output to the browser before the
|
||||||
|
template, or else the header may fail.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>using insert to write a WML Content-Type header</title>
|
||||||
|
<programlisting>
|
||||||
|
// be sure apache is configure for the .wml extensions!
|
||||||
|
// put this function somewhere in your application, or in Smarty.addons.php
|
||||||
|
function insert_header() {
|
||||||
|
// this function expects $content argument
|
||||||
|
extract(func_get_arg(0));
|
||||||
|
if(empty($content))
|
||||||
|
return;
|
||||||
|
header($content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// your Smarty template _must_ begin with the insert tag example:
|
||||||
|
|
||||||
|
{insert name=header content="Content-Type: text/vnd.wap.wml"}
|
||||||
|
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
|
||||||
|
|
||||||
|
<!-- begin new wml deck -->
|
||||||
|
<wml>
|
||||||
|
<!-- begin first card -->
|
||||||
|
<card>
|
||||||
|
<do type="accept">
|
||||||
|
<go href="#two"/>
|
||||||
|
</do>
|
||||||
|
<p>
|
||||||
|
Welcome to WAP with Smarty!
|
||||||
|
Press OK to continue...
|
||||||
|
</p>
|
||||||
|
</card>
|
||||||
|
<!-- begin second card -->
|
||||||
|
<card id="two">
|
||||||
|
<p>
|
||||||
|
Pretty easy isn't it?
|
||||||
|
</p>
|
||||||
|
</card>
|
||||||
|
</wml></programlisting>
|
||||||
|
</example>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="tips.componentized.templates">
|
||||||
|
<title>Componentized Templates</title>
|
||||||
|
<para>
|
||||||
|
This tip is a bit of a hack, but still a neat idea. Use at your own
|
||||||
|
risk. ;-)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Traditionally, programming templates into your applications goes as
|
||||||
|
follows: First, you accumulate your variables within your PHP
|
||||||
|
application, (maybe with database queries.) Then, you instantiate your
|
||||||
|
Smarty object, assign the variables and display the template. So lets
|
||||||
|
say for example we have a stock ticker on our template. We would
|
||||||
|
collect the stock data in our application, then assign these variables
|
||||||
|
in the template and display it. Now wouldn't it be nice if you could
|
||||||
|
add this stock ticker to any application by merely including the
|
||||||
|
template, and not worry about fetching the data up front?
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You can embed PHP into your templates with the {php}{/php} tags.
|
||||||
|
With this, you can setup self contained templates with their own
|
||||||
|
data structures for assigning their own variables. With the logic
|
||||||
|
embedded like this, you can keep the template & logic together. This
|
||||||
|
way no matter where the template source is coming from, it is always
|
||||||
|
together as one component.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>componentized template</title>
|
||||||
|
<programlisting>
|
||||||
|
{* Smarty *}
|
||||||
|
|
||||||
|
{php}
|
||||||
|
|
||||||
|
// setup our function for fetching stock data
|
||||||
|
function fetch_ticker($symbol,&$ticker_name,&$ticker_price) {
|
||||||
|
// put logic here that fetches $ticker_name
|
||||||
|
// and $ticker_price from some resource
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the function
|
||||||
|
fetch_ticker("YHOO",$ticker_name,$ticker_price);
|
||||||
|
|
||||||
|
// assign template variables
|
||||||
|
$this->assign("ticker_name",$ticker_name);
|
||||||
|
$this->assign("ticker_price",$ticker_price);
|
||||||
|
|
||||||
|
{/php}
|
||||||
|
|
||||||
|
Stock Name: {$ticker_name} Stock Price: {$ticker_price}</programlisting>
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
As of Smarty 1.5.0, there is even a cleaner way. You can include php in
|
||||||
|
your templates with the {include_php ...} tag. This way you can keep
|
||||||
|
your PHP logic separated from the template logic. See the <link
|
||||||
|
linkend="builtin.functions.include.php">include_php</link> function for
|
||||||
|
more information.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>componentized template with include_php</title>
|
||||||
|
<programlisting>
|
||||||
|
load_ticker.php
|
||||||
|
---------------
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// setup our function for fetching stock data
|
||||||
|
function fetch_ticker($symbol,&$ticker_name,&$ticker_price) {
|
||||||
|
// put logic here that fetches $ticker_name
|
||||||
|
// and $ticker_price from some resource
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the function
|
||||||
|
fetch_ticker("YHOO",$ticker_name,$ticker_price);
|
||||||
|
|
||||||
|
// assign template variables
|
||||||
|
$this->assign("ticker_name",$ticker_name);
|
||||||
|
$this->assign("ticker_price",$ticker_price);
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
index.tpl
|
||||||
|
---------
|
||||||
|
|
||||||
|
{* Smarty *}
|
||||||
|
|
||||||
|
{include_php file="load_ticker.php"}
|
||||||
|
|
||||||
|
Stock Name: {$ticker_name} Stock Price: {$ticker_price}</programlisting>
|
||||||
|
</example>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Obfuscating E-mail Addresses</title>
|
||||||
|
<para>
|
||||||
|
Do you ever wonder how your E-mail address gets on so many spam mailing
|
||||||
|
lists? One way spammers collect E-mail addresses is from web pages. To
|
||||||
|
help combat this problem, you can make your E-mail address show up in a
|
||||||
|
scrambled looking form in the HTML source, yet it it will look and work
|
||||||
|
correctly in the browser. This is done with the escape modifier.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>Example of Obfuscating an E-mail Address</title>
|
||||||
|
<programlisting>
|
||||||
|
|
||||||
|
index.tpl
|
||||||
|
---------
|
||||||
|
|
||||||
|
Send inquiries to
|
||||||
|
<a href="mailto:{$EmailAddress|escape:"hex"}>{$EmailAddress|escape:"hexentity"}</a>
|
||||||
|
|
||||||
|
OUTPUT:
|
||||||
|
|
||||||
|
Send inquiries to
|
||||||
|
<a
|
||||||
|
href="mailto:%62%6f%62%40%6d%65%2e%6e%65%74">&#x62;&#x6f;&#x62;&#x40;&#x6d;&#x65;&#x2e;&#x6e;&#x65;&#x74;</a>
|
||||||
|
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Although this looks like a mess in the HTML source, it will render
|
||||||
|
correctly in your browser, and the mailto: hyperlink will go to the correct
|
||||||
|
address.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TECHNICAL NOTE: This method isn't 100% foolproof. Although highly unlikely,
|
||||||
|
a spammer could conceivably write his e-mail collecter to decode these
|
||||||
|
values.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="resources">
|
||||||
|
<title>Resources</title>
|
||||||
|
<para>
|
||||||
|
Smarty's homepage is located at http://www.phpinsider.com/php/code/Smarty/.
|
||||||
|
You can join the mailing list by sending an e-mail to
|
||||||
|
subscribe-smarty@lists.ispi.net. An archive of the mailing list can be
|
||||||
|
viewed at http://marc.theaimsgroup.com/?l=smarty&r=1&w=2
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="bugs">
|
||||||
|
<title>BUGS</title>
|
||||||
|
<para>
|
||||||
|
Check the BUGS file that comes with the latest distribution of Smarty, or
|
||||||
|
check the website.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
</part>
|
46
docs/common.dsl
Normal file
46
docs/common.dsl
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
;; -*- Scheme -*-
|
||||||
|
;;
|
||||||
|
;; $Id$
|
||||||
|
;;
|
||||||
|
;; This file contains stylesheet customization common to the HTML
|
||||||
|
;; and print versions.
|
||||||
|
;;
|
||||||
|
|
||||||
|
;; Stylesheets Localization
|
||||||
|
(define %default-language% "en")
|
||||||
|
|
||||||
|
(define %use-id-as-filename% #t)
|
||||||
|
(define %gentext-nav-tblwidth% "100%")
|
||||||
|
(define %refentry-function% #t)
|
||||||
|
(define %refentry-generate-name% #f)
|
||||||
|
(define %funcsynopsis-style% 'ansi)
|
||||||
|
(define ($legalnotice-link-file$ legalnotice)
|
||||||
|
(string-append "copyright" %html-ext%))
|
||||||
|
(define %generate-legalnotice-link% #t)
|
||||||
|
(define %footnotes-at-end% #t)
|
||||||
|
(define %force-chapter-toc% #t)
|
||||||
|
(define newline "\U-000D")
|
||||||
|
(define %number-programlisting-lines% #f)
|
||||||
|
(define %linenumber-mod% 1)
|
||||||
|
(define %shade-verbatim% #t)
|
||||||
|
|
||||||
|
(define ($generate-book-lot-list$)
|
||||||
|
;; REFENTRY generate-book-lot-list
|
||||||
|
;; PURP Which Lists of Titles should be produced for Books?
|
||||||
|
;; DESC
|
||||||
|
;; This parameter should be a list (possibly empty) of the elements
|
||||||
|
;; for which Lists of Titles should be produced for each 'Book'.
|
||||||
|
;;
|
||||||
|
;; It is meaningless to put elements that do not have titles in this
|
||||||
|
;; list. If elements with optional titles are placed in this list, only
|
||||||
|
;; the instances of those elements that do have titles will appear in
|
||||||
|
;; the LOT.
|
||||||
|
;;
|
||||||
|
;; /DESC
|
||||||
|
;; AUTHOR N/A
|
||||||
|
;; /REFENTRY
|
||||||
|
(list (normalize "table")))
|
||||||
|
|
||||||
|
(define (php-code code)
|
||||||
|
(make processing-instruction
|
||||||
|
data: (string-append "php " code "?")))
|
4054
docs/designers.sgml
Normal file
4054
docs/designers.sgml
Normal file
File diff suppressed because it is too large
Load Diff
198
docs/getting-started.sgml
Normal file
198
docs/getting-started.sgml
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<part id="getting.started">
|
||||||
|
<title>Getting Started</title>
|
||||||
|
<chapter id="overview">
|
||||||
|
<title>Overview</title>
|
||||||
|
<sect1 id="what.is.smarty">
|
||||||
|
<title>What is Smarty?</title>
|
||||||
|
<para>
|
||||||
|
Smarty is a template engine for PHP. One of the unique aspects about
|
||||||
|
Smarty is that it compiles the template files into native PHP scripts
|
||||||
|
upon the first invocation. After that, it just executes the compiled
|
||||||
|
PHP scripts. Therefore, there is no costly template file parsing for
|
||||||
|
each request, and each template can take full advantage of PHP compiler
|
||||||
|
cache solutions such as Zend Cache (http://www.zend.com) or APC
|
||||||
|
(http://apc.communityconnect.com).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some of Smarty's features:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>It is extremely fast.</para></listitem>
|
||||||
|
<listitem><para>It is efficient since the PHP parser does the
|
||||||
|
dirty work.</para></listitem>
|
||||||
|
<listitem><para>No template parsing overhead, only compiles once.</para></listitem>
|
||||||
|
<listitem><para>It is smart about recompiling only the template
|
||||||
|
files that have changed.</para></listitem>
|
||||||
|
<listitem><para>You can make <link linkend="bundled.plugins.commands">custom
|
||||||
|
functions</link> and custom <link linkend="variable.modifiers">variable
|
||||||
|
modifiers</link>, so the template language is extremely extensible.</para></listitem>
|
||||||
|
<listitem><para>Configurable template delimiter tag syntax, so you can use
|
||||||
|
{}, {{}}, <!--{}-->, etc.</para></listitem>
|
||||||
|
<listitem><para>The if/elseif/else/endif constructs are passed to the
|
||||||
|
PHP parser, so the {if ...} expression syntax can be as simple or as complex
|
||||||
|
as you like.</para></listitem>
|
||||||
|
<listitem><para>Unlimited nesting of sections, ifs, etc. allowed.</para></listitem>
|
||||||
|
<listitem><para>It is possible to embed PHP code right in your template files,
|
||||||
|
although this may not be needed (nor recommended)
|
||||||
|
since the engine is so customizable.</para></listitem>
|
||||||
|
<listitem><para>Built-in caching support (new in 1.3.0)</para></listitem>
|
||||||
|
<listitem><para>Arbitrary template sources (new in 1.4.0)</para></listitem>
|
||||||
|
<listitem><para>Custom cache handling functions (new in 1.4.7)</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="how.smarty.works">
|
||||||
|
<title>How Smarty works</title>
|
||||||
|
|
||||||
|
<sect2 id="features.compiling"><title>Compiling</title>
|
||||||
|
<para>
|
||||||
|
Smarty compiles the templates into native PHP code on-the-fly. The actual
|
||||||
|
PHP scripts that are generated are created implicitly, so theoretically you
|
||||||
|
should never have to worry about touching these files, or even know of their
|
||||||
|
existence. The exception to this is debugging Smarty template syntax errors,
|
||||||
|
discussed later in this document.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="features.caching">
|
||||||
|
<title>Caching</title>
|
||||||
|
<para>
|
||||||
|
Smarty can cache the output of your generated templates. By default
|
||||||
|
this is disabled. If you <link linkend="variable.caching">enable
|
||||||
|
caching</link>, Smarty will store a copy of the generated template
|
||||||
|
output, and use this until the copy <link
|
||||||
|
linkend="variable.cache.lifetime">expires</link>, regenerating a new
|
||||||
|
one. The default cache expire time can be configured from the
|
||||||
|
class. The exception to the rule is the <link
|
||||||
|
linkend="builtin.functions.insert">insert</link> tag. Anything
|
||||||
|
generated by the insert tag is not cached, but run dynamically on
|
||||||
|
every invocation, even within cached content.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TECHNICAL NOTE: Any time you change a template, change values in
|
||||||
|
config files or change the content that gets displayed in a
|
||||||
|
template, you can turn on compile_check to regenerate the caches
|
||||||
|
that are affected, or wait for the cache to expire to see the
|
||||||
|
results of the changes. You clear caches manually by deleting files
|
||||||
|
from the cache directory, programatically with <link
|
||||||
|
linkend="api.clear.cache">clear_cache</link> or <link
|
||||||
|
linkend="api.clear.all.cache">clear_all_cache</link>, or turn on
|
||||||
|
$compile_check (or $force_compile).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TECHNICAL NOTE: As of Smarty 1.4.6, if you have caching enabled AND
|
||||||
|
you have compile_check enabled, the cached file will regenerate if
|
||||||
|
an involved template or config file has been modified, regardless
|
||||||
|
of the cache expire time. This results in a slight performance hit
|
||||||
|
since it has to check the templates and config files for
|
||||||
|
modification times. Therefore if you are not actively changing
|
||||||
|
templates or config files, it is advisable to leave compile_check
|
||||||
|
off. As of Smarty 1.4.7, enabling $force_compile will cause cache
|
||||||
|
files to always be regenerated.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="installation">
|
||||||
|
<title>Installation</title>
|
||||||
|
|
||||||
|
<sect1 id="installation.requirements">
|
||||||
|
<title>Requirements</title>
|
||||||
|
<para>
|
||||||
|
Smarty requires PHP 4.0.4pl1 or later. See the
|
||||||
|
<link linkend="bugs">BUGS</link> section for caveats.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="installation.smarty">
|
||||||
|
<title>Installing Smarty</title>
|
||||||
|
<para>
|
||||||
|
Installing Smarty is fairly straightforward, there are a few things to
|
||||||
|
be aware of. Smarty creates PHP scripts from the templates. This
|
||||||
|
usually means allowing user "nobody" (or whomever the web server runs
|
||||||
|
as) to have permission to write the files. Each installation of a
|
||||||
|
Smarty application minimally needs a templates directory and a compiled
|
||||||
|
templates directory. If you use configuration files you will also need
|
||||||
|
a directory for those. By default these are named "templates",
|
||||||
|
"templates_c" and "configs" respectively. If you plan on using caching,
|
||||||
|
you will need to create a "cache" directory, also with permission to
|
||||||
|
write files.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TECHNICAL NOTE: You can get around the need to allow the web server
|
||||||
|
user write access to compile templates. Smarty needs to compile the
|
||||||
|
templates only once. This can be done from the command line, using the
|
||||||
|
CGI version of PHP. example: "php -q index.php". Once the templates are
|
||||||
|
compiled, they should run fine from the web environment. If you change
|
||||||
|
a template, you must recompile from the command line again. If you do
|
||||||
|
not have the CGI version of PHP available and you are concerned about
|
||||||
|
world-writable directory access, you can chmod 777 the compile_dir, let
|
||||||
|
the templates compile once as the web server user, then change the
|
||||||
|
directory mode to 755. If you are using the caching feature of Smarty,
|
||||||
|
the cache directory must always have write access for the web server
|
||||||
|
user.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TECHNICAL NOTE: If you do not have access to the php.ini file, you can
|
||||||
|
change non-server settings (such as your include_path) with the
|
||||||
|
ini_set() command (available in PHP 4.0.4 or later.) example:
|
||||||
|
ini_set("include_path",".:/usr/local/lib/php");
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Copy the Smarty.class.php, Smarty.addons.php and Config_File.class.php
|
||||||
|
scripts to a directory that is in your PHP include_path. NOTE: PHP will
|
||||||
|
try to create a directory alongside the executing script called
|
||||||
|
"templates_c". Be sure that directory permissions allow this to happen.
|
||||||
|
You will see PHP error messages if this fails. You can also create the
|
||||||
|
directory yourself before hand, and change the file ownership
|
||||||
|
accordingly. See below.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TECHNICAL NOTE: If you don't want to use include_path to find the
|
||||||
|
Smarty files, you can set the SMARTY_DIR constant to the full path to
|
||||||
|
your Smarty library files. Be sure the path ends with a slash!
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>Example of installing Smarty</title>
|
||||||
|
<screen>
|
||||||
|
# be sure you are in the web server document tree
|
||||||
|
# this assumes your web server runs as user "nobody"
|
||||||
|
# and you are in a un*x environment
|
||||||
|
gtar -zxvf Smarty-[version].tar.gz
|
||||||
|
mkdir templates_c
|
||||||
|
chown nobody:nobody templates_c
|
||||||
|
chmod 700 templates_c
|
||||||
|
# if you are using caching, do the following
|
||||||
|
mkdir cache
|
||||||
|
chown nobody:nobody cache
|
||||||
|
chmod 700 cache</screen>
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Next, try running the index.php script from your web browser.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="smarty.constants">
|
||||||
|
<title>Constants</title>
|
||||||
|
<para></para>
|
||||||
|
|
||||||
|
<sect2 id="constant.smarty.dir">
|
||||||
|
<title>SMARTY_DIR</title>
|
||||||
|
<para>
|
||||||
|
This should be the full system path to the location of the Smarty
|
||||||
|
class files. If this is not defined, then Smarty will attempt to
|
||||||
|
determine the appropriate value automatically. If defined, the path
|
||||||
|
must end with a slash.
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<title>SMARTY_DIR</title>
|
||||||
|
<programlisting>
|
||||||
|
// set path to Smarty directory
|
||||||
|
define("SMARTY_DIR","/usr/local/lib/php/Smarty/");
|
||||||
|
|
||||||
|
require_once(SMARTY_DIR."Smarty.class.php");</programlisting>
|
||||||
|
</example>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
</part>
|
336
docs/html-common.dsl
Normal file
336
docs/html-common.dsl
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
;; -*- Scheme -*-
|
||||||
|
;;
|
||||||
|
;; $Id$
|
||||||
|
;;
|
||||||
|
|
||||||
|
;; Returns the depth of the auto-generated TOC (table of contents) that
|
||||||
|
;; should be made at the nd-level
|
||||||
|
(define (toc-depth nd)
|
||||||
|
(if (string=? (gi nd) (normalize "book"))
|
||||||
|
3 ; the depth of the top-level TOC
|
||||||
|
1 ; the depth of all other TOCs
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(element (funcdef function)
|
||||||
|
($bold-seq$
|
||||||
|
(make sequence
|
||||||
|
(process-children)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(define (is-true-optional nl)
|
||||||
|
(and (equal? (gi (parent nl)) (normalize "parameter"))
|
||||||
|
(equal? 0 (string-length (strip (data (preced nl)))))
|
||||||
|
(equal? 0 (string-length (strip (data (follow nl)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(define (has-true-optional nl)
|
||||||
|
(is-true-optional
|
||||||
|
(node-list-first-element
|
||||||
|
(select-elements
|
||||||
|
(descendants nl)
|
||||||
|
(normalize "optional"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(define (count-true-optionals nl)
|
||||||
|
(let loop
|
||||||
|
((result 0)
|
||||||
|
(nl (select-elements (descendants nl) (normalize "optional")))
|
||||||
|
)
|
||||||
|
(if(node-list-empty? nl)
|
||||||
|
result
|
||||||
|
(if(is-true-optional(node-list-first nl))
|
||||||
|
(loop (+ result 1) (node-list-rest nl))
|
||||||
|
(loop result (node-list-rest nl))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
;; there are two different kinds of optionals
|
||||||
|
;; optional parameters and optional parameter parts
|
||||||
|
;; an optional parameter is identified by an optional tag
|
||||||
|
;; with a parameter tag as its parent
|
||||||
|
;; and only whitespace between them
|
||||||
|
(element optional
|
||||||
|
;;check for true optional parameter
|
||||||
|
(if (is-true-optional (current-node))
|
||||||
|
;; yes - handle '[...]' in paramdef
|
||||||
|
(process-children-trim)
|
||||||
|
;; no - do '[...]' output
|
||||||
|
(make sequence
|
||||||
|
(literal %arg-choice-opt-open-str%)
|
||||||
|
(process-children-trim)
|
||||||
|
(literal %arg-choice-opt-close-str%)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; now this is going to be tricky
|
||||||
|
(element paramdef
|
||||||
|
(make sequence
|
||||||
|
;; special treatment for first parameter in funcsynopsis
|
||||||
|
(if (equal? (child-number (current-node)) 1)
|
||||||
|
;; is first ?
|
||||||
|
(make sequence
|
||||||
|
;; start parameter list
|
||||||
|
(literal "(")
|
||||||
|
;; is optional ?
|
||||||
|
( if (has-true-optional (current-node))
|
||||||
|
(literal %arg-choice-opt-open-str%)
|
||||||
|
(empty-sosofo)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;; not first
|
||||||
|
(empty-sosofo)
|
||||||
|
)
|
||||||
|
|
||||||
|
;;
|
||||||
|
(process-children-trim)
|
||||||
|
|
||||||
|
;; special treatment for last parameter
|
||||||
|
(if (equal? (gi (ifollow (current-node))) (normalize "paramdef"))
|
||||||
|
;; more parameters will follow
|
||||||
|
(make sequence
|
||||||
|
;; next is optional ?
|
||||||
|
( if (has-true-optional (ifollow (current-node)))
|
||||||
|
;; optional
|
||||||
|
(make sequence
|
||||||
|
(literal " ")
|
||||||
|
(literal %arg-choice-opt-open-str%)
|
||||||
|
)
|
||||||
|
;; not optional
|
||||||
|
(empty-sosofo)
|
||||||
|
)
|
||||||
|
(literal ", " )
|
||||||
|
)
|
||||||
|
;; last parameter
|
||||||
|
(make sequence
|
||||||
|
(literal
|
||||||
|
(let loop ((result "")(count (count-true-optionals (parent (current-node)))))
|
||||||
|
(if (<= count 0)
|
||||||
|
result
|
||||||
|
(loop (string-append result %arg-choice-opt-close-str%)(- count 1))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
( literal ")" )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(element function
|
||||||
|
(let* ((function-name (data (current-node)))
|
||||||
|
(linkend
|
||||||
|
(string-append
|
||||||
|
"function."
|
||||||
|
(string-replace
|
||||||
|
(string-replace function-name "_" "-")
|
||||||
|
"::" ".")))
|
||||||
|
(target (element-with-id linkend))
|
||||||
|
(parent-gi (gi (parent))))
|
||||||
|
(cond
|
||||||
|
;; function names should be plain in FUNCDEF
|
||||||
|
((equal? parent-gi "funcdef")
|
||||||
|
(process-children))
|
||||||
|
|
||||||
|
;; if a valid ID for the target function is not found, or if the
|
||||||
|
;; FUNCTION tag is within the definition of the same function,
|
||||||
|
;; make it bold, add (), but don't make a link
|
||||||
|
((or (node-list-empty? target)
|
||||||
|
(equal? (case-fold-down
|
||||||
|
(data (node-list-first
|
||||||
|
(select-elements
|
||||||
|
(node-list-first
|
||||||
|
(children
|
||||||
|
(select-elements
|
||||||
|
(children
|
||||||
|
(ancestor-member (parent) (list "refentry")))
|
||||||
|
"refnamediv")))
|
||||||
|
"refname"))))
|
||||||
|
function-name))
|
||||||
|
($bold-seq$
|
||||||
|
(make sequence
|
||||||
|
(process-children)
|
||||||
|
(literal "()"))))
|
||||||
|
|
||||||
|
;; else make a link to the function and add ()
|
||||||
|
(else
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list
|
||||||
|
(list "HREF" (href-to target)))
|
||||||
|
($bold-seq$
|
||||||
|
(make sequence
|
||||||
|
(process-children)
|
||||||
|
(literal
|
||||||
|
)
|
||||||
|
(literal "()"))))))))
|
||||||
|
|
||||||
|
|
||||||
|
(element classname
|
||||||
|
(let* ((class-name (data (current-node)))
|
||||||
|
(linkend
|
||||||
|
(string-append
|
||||||
|
"class."
|
||||||
|
(string-replace
|
||||||
|
(case-fold-down class-name) "_" "-")))
|
||||||
|
(target (element-with-id linkend))
|
||||||
|
(parent-gi (gi (parent))))
|
||||||
|
(cond
|
||||||
|
;; function names should be plain in SYNOPSIS
|
||||||
|
((equal? parent-gi "synopsis")
|
||||||
|
(process-children))
|
||||||
|
|
||||||
|
;; if a valid ID for the target class is not found, or if the
|
||||||
|
;; CLASSNAME tag is within the definition of the same class,
|
||||||
|
;; make it bold, but don't make a link
|
||||||
|
((or (node-list-empty? target)
|
||||||
|
(equal? (case-fold-down
|
||||||
|
(data (node-list-first
|
||||||
|
(select-elements
|
||||||
|
(node-list-first
|
||||||
|
(children
|
||||||
|
(select-elements
|
||||||
|
(children
|
||||||
|
(ancestor-member (parent) (list "refentry")))
|
||||||
|
"refnamediv")))
|
||||||
|
"refname"))))
|
||||||
|
class-name))
|
||||||
|
($bold-seq$
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
;; else make a link to the function and add ()
|
||||||
|
(else
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list
|
||||||
|
(list "HREF" (href-to target)))
|
||||||
|
($bold-seq$
|
||||||
|
(process-children)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(element constant
|
||||||
|
(let* ((constant-name (data (current-node)))
|
||||||
|
(linkend
|
||||||
|
(string-append "constant."
|
||||||
|
(case-fold-down
|
||||||
|
(string-replace constant-name "_" "-"))))
|
||||||
|
(target (element-with-id linkend))
|
||||||
|
(parent-gi (gi (parent))))
|
||||||
|
(cond
|
||||||
|
; ;; constant names should be plain in FUNCDEF
|
||||||
|
; ((equal? parent-gi "funcdef")
|
||||||
|
; (process-children))
|
||||||
|
|
||||||
|
;; if a valid ID for the target constant is not found, or if the
|
||||||
|
;; CONSTANT tag is within the definition of the same constant,
|
||||||
|
;; make it bold, add (), but don't make a link
|
||||||
|
((or (node-list-empty? target)
|
||||||
|
(equal? (case-fold-down
|
||||||
|
(data (node-list-first
|
||||||
|
(select-elements
|
||||||
|
(node-list-first
|
||||||
|
(children
|
||||||
|
(select-elements
|
||||||
|
(children
|
||||||
|
(ancestor-member (parent) (list "refentry")))
|
||||||
|
"refnamediv")))
|
||||||
|
"refname"))))
|
||||||
|
constant-name))
|
||||||
|
($bold-mono-seq$
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
;; else make a link to the function and add ()
|
||||||
|
(else
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list
|
||||||
|
(list "HREF" (href-to target)))
|
||||||
|
($bold-mono-seq$
|
||||||
|
(process-children)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(element example
|
||||||
|
(make sequence
|
||||||
|
(make element gi: "TABLE"
|
||||||
|
attributes: (list
|
||||||
|
(list "WIDTH" "100%")
|
||||||
|
(list "BORDER" "0")
|
||||||
|
(list "CELLPADDING" "0")
|
||||||
|
(list "CELLSPACING" "0")
|
||||||
|
(list "CLASS" "EXAMPLE"))
|
||||||
|
(make element gi: "TR"
|
||||||
|
(make element gi: "TD"
|
||||||
|
($formal-object$))))))
|
||||||
|
|
||||||
|
|
||||||
|
(element (paramdef parameter)
|
||||||
|
(make sequence
|
||||||
|
font-posture: 'italic
|
||||||
|
(process-children-trim)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(mode book-titlepage-recto-mode
|
||||||
|
(element authorgroup
|
||||||
|
(process-children))
|
||||||
|
|
||||||
|
(element author
|
||||||
|
(let ((author-name (author-string))
|
||||||
|
(author-affil (select-elements (children (current-node))
|
||||||
|
(normalize "affiliation"))))
|
||||||
|
(make sequence
|
||||||
|
(make element gi: "DIV"
|
||||||
|
attributes: (list (list "CLASS" (gi)))
|
||||||
|
(literal author-name))
|
||||||
|
(process-node-list author-affil))))
|
||||||
|
)
|
||||||
|
|
||||||
|
(define (chunk-element-list)
|
||||||
|
(list (normalize "preface")
|
||||||
|
(normalize "chapter")
|
||||||
|
(normalize "appendix")
|
||||||
|
(normalize "article")
|
||||||
|
(normalize "glossary")
|
||||||
|
(normalize "bibliography")
|
||||||
|
(normalize "index")
|
||||||
|
(normalize "colophon")
|
||||||
|
(normalize "setindex")
|
||||||
|
(normalize "reference")
|
||||||
|
(normalize "refentry")
|
||||||
|
(normalize "part")
|
||||||
|
(normalize "sect1")
|
||||||
|
(normalize "sect2")
|
||||||
|
(normalize "section")
|
||||||
|
(normalize "book") ;; just in case nothing else matches...
|
||||||
|
(normalize "set") ;; sets are definitely chunks...
|
||||||
|
))
|
||||||
|
|
||||||
|
(define ($section-body$)
|
||||||
|
(make element gi: "DIV"
|
||||||
|
attributes: (list (list "CLASS" (gi)))
|
||||||
|
($section-separator$)
|
||||||
|
($section-title$)
|
||||||
|
|
||||||
|
(if (or (not (node-list-empty? (select-elements (children (current-node))
|
||||||
|
(normalize "sect2"))))
|
||||||
|
(not (node-list-empty? (select-elements (children (current-node))
|
||||||
|
(normalize "sect3")))))
|
||||||
|
(build-toc (current-node) 1)
|
||||||
|
(empty-sosofo))
|
||||||
|
|
||||||
|
(process-children)))
|
||||||
|
|
21
docs/html.dsl
Normal file
21
docs/html.dsl
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
|
||||||
|
<!ENTITY docbook.dsl SYSTEM "/usr/share/sgml/docbook/html/docbook.dsl" CDATA DSSSL>
|
||||||
|
<!ENTITY html-common.dsl SYSTEM "html-common.dsl">
|
||||||
|
<!ENTITY common.dsl SYSTEM "common.dsl">
|
||||||
|
]>
|
||||||
|
|
||||||
|
<style-sheet>
|
||||||
|
<style-specification id="docbook-smarty-html" use="docbook">
|
||||||
|
<style-specification-body>
|
||||||
|
|
||||||
|
(define %html-ext% ".html")
|
||||||
|
|
||||||
|
&html-common.dsl;
|
||||||
|
&common.dsl;
|
||||||
|
|
||||||
|
</style-specification-body>
|
||||||
|
</style-specification>
|
||||||
|
|
||||||
|
<external-specification id="docbook" document="docbook.dsl">
|
||||||
|
|
||||||
|
</style-sheet>
|
34
docs/manual.sgml
Normal file
34
docs/manual.sgml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
|
||||||
|
<!ENTITY preface SYSTEM "preface.sgml">
|
||||||
|
<!ENTITY getting.started SYSTEM "getting-started.sgml">
|
||||||
|
<!ENTITY smarty.for.designers SYSTEM "designers.sgml">
|
||||||
|
<!ENTITY smarty.for.programmers SYSTEM "programmers.sgml">
|
||||||
|
<!ENTITY appendixes SYSTEM "appendixes.sgml">
|
||||||
|
]>
|
||||||
|
|
||||||
|
<book id="index">
|
||||||
|
<bookinfo id="bookinfo">
|
||||||
|
<title>Smarty - the compiling PHP template engine</title>
|
||||||
|
<authorgroup id="authors">
|
||||||
|
<author>
|
||||||
|
<firstname>Monte</firstname><surname>Ohrt <monte@ispi.net></surname>
|
||||||
|
</author>
|
||||||
|
<author>
|
||||||
|
<firstname>Andrei</firstname><surname>Zmievski <andrei@php.net></surname>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
<edition>Version 2.0</edition>
|
||||||
|
<copyright>
|
||||||
|
<year>2001</year>
|
||||||
|
<year>2002</year>
|
||||||
|
<holder>ispi of Lincoln, Inc.</holder>
|
||||||
|
</copyright>
|
||||||
|
</bookinfo>
|
||||||
|
|
||||||
|
&preface;
|
||||||
|
&getting.started;
|
||||||
|
&smarty.for.designers;
|
||||||
|
&smarty.for.programmers;
|
||||||
|
&appendixes;
|
||||||
|
|
||||||
|
</book>
|
69
docs/preface.sgml
Normal file
69
docs/preface.sgml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<preface id="preface">
|
||||||
|
<title>Preface</title>
|
||||||
|
<para>
|
||||||
|
It is undoubtedly one of the most asked questions on the PHP mailing
|
||||||
|
lists: how do I make my PHP scripts independent of the layout? While
|
||||||
|
PHP is billed as "HTML embedded scripting language", after writing a
|
||||||
|
couple of projects that mixed PHP and HTML freely one comes up with the
|
||||||
|
idea that separation of form and content is a Good Thing [TM]. In
|
||||||
|
addition, in many companies the roles of layout designer and programmer
|
||||||
|
are separate. Consequently, the search for a templating solution
|
||||||
|
ensues.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In our company for example, the development of an application goes on
|
||||||
|
as follows: After the requirements docs are done, the interface
|
||||||
|
designer makes mockups of the interface and gives them to the
|
||||||
|
programmer. The programmer implements business logic in PHP and uses
|
||||||
|
interface mockups to create skeleton templates. The project is then
|
||||||
|
handed off to the HTML designer/web page layout person who brings the
|
||||||
|
templates up to their full glory. The project may go back and forth
|
||||||
|
between programming/HTML a couple of times. Thus, it's important to
|
||||||
|
have good template support because programmers don't want anything to
|
||||||
|
do with HTML and don't want HTML designers mucking around with PHP
|
||||||
|
code. Designers need support for config files, dynamic blocks and
|
||||||
|
other interface issues, but they don't want to have to deal with
|
||||||
|
intricacies of the PHP programming language.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Looking at many templating solutions available for PHP today, most of
|
||||||
|
them provide a rudimentary way of substituting variables into templates
|
||||||
|
and do a limited form of dynamic block functionality. But our needs
|
||||||
|
required a bit more than that. We didn't want programmers to be dealing
|
||||||
|
with HTML layout at ALL, but this was almost inevitable. For instance,
|
||||||
|
if a designer wanted background colors to alternate on dynamic blocks,
|
||||||
|
this had to be worked out with the programmer in advance. We also
|
||||||
|
needed designers to be able to use their own configuration files, and
|
||||||
|
pull variables from them into the templates. The list goes on.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We started out writing out a spec for a template engine back in late
|
||||||
|
1999. After finishing the spec, we began to work on a template engine
|
||||||
|
written in C that would hopefully be accepted for inclusion with PHP.
|
||||||
|
Not only did we run into many complicated technical barriers, but there
|
||||||
|
was also much heated debate about exactly what a template engine should
|
||||||
|
and should not do. From this experience, we decided that the template
|
||||||
|
engine should be written in PHP as a class, for anyone to use as they
|
||||||
|
see fit. So we wrote an engine that did just that and
|
||||||
|
<productname>SmartTemplate</productname> came into existence (note: this
|
||||||
|
class was never submitted to the public). It was a class that did
|
||||||
|
almost everything we wanted: regular variable substitution, supported
|
||||||
|
including other templates, integration with config files, embedding PHP
|
||||||
|
code, limited 'if' statement functionality and much more robust dynamic
|
||||||
|
blocks which could be multiply nested. It did all this with regular
|
||||||
|
expressions and the code turned out to be rather, shall we say,
|
||||||
|
impenetrable. It was also noticably slow in large applications from all
|
||||||
|
the parsing and regular expression work it had to do on each
|
||||||
|
invocation. The biggest problem from a programmer's point of view was
|
||||||
|
all the necessary work in the PHP script to setup and process templates
|
||||||
|
and dynamic blocks. How do we make this easier?
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Then came the vision of what ultimately became Smarty. We know how fast
|
||||||
|
PHP code is without the overhead of template parsing. We also know how
|
||||||
|
meticulous and overbearing the PHP language may look to the average
|
||||||
|
designer, and this could be masked with a much simpler templating
|
||||||
|
syntax. So what if we combined the two strengths? Thus, Smarty was
|
||||||
|
born...
|
||||||
|
</para>
|
||||||
|
</preface>
|
2030
docs/programmers.sgml
Normal file
2030
docs/programmers.sgml
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user