Patron is a template engine for PHP5.4+. It facilitates a mangeable way to seperate application logic and content from its presentation. Templates are usually written in HTML and include keywords that are replaced as the template is parsed, and special markups that control the logic of the template or fetch data.
A typical example:
<p:articles limit="10">
<p:foreach>
<article class="#{@css_class}">
<h1>#{@title}</h1>
<div class="article-body">#{@=}</div>
<p:if test="@comments">
<section class="article-comments">
<h2>Comments</h2>
<p:foreach in="@comments">
<article class="#{@css_class}">
<header>
<h3>Comment №#{self.position} by #{@author}</h3>
</header>
<div class="comment-body">#{@=}</div>
</article>
</p:foreach>
</section>
</p:if>
</article>
</p:foreach>
<p:pager />
</p:articles>
- The markup set is easily extensible.
- Blocks have a scope, similar to
this
in javascript. - Easy to translate using the
#{t:String to translate}
notation.
Variables are outputted with the #{<expression>}
notation, where <expression>
is an
expression. They are escaped unless the =
modifier is used:
#{@title}
#{@title.shuffle()} <!-- `title` is passed to str_shuffle() -->
#{@title=} <!-- `title` is not escaped -->
The package defines the following markups, that can be used within templates.
Provides a simple if-then conditionality.
<p:if
test = expression
select = expression
equals = value>
<!-- Content: p:with-param*, template -->
</p:if>
Either test
or select
and an operator (e.g. equals
) should be defined. The test is silent,
and should not generate notices.
<p:if test="@has_title">This article has a title</p:if>
<p:if test="@has_title.not()">This article has no title</p:if>
<p:if select="@comments_count" equals="10">This article has 10 comments</p:if>
Selects one among a number of possible alternatives.
<!-- Category: instruction -->
<p:choose>
<!-- Content: (p:when+, p:otherwise?) -->
</p:choose>
<p:when
test = boolean-expression>
<!-- Content: template -->
</p:when>
<p:otherwise>
<!-- Content: template -->
</p:otherwise>
It consists of a sequence of p:when
elements followed by an optional p:otherwise
element. Each p:when
element has a single attribute, test, which specifies an expression.
The content of the p:when
and p:otherwise
elements is a template. When an p:choose
element is processed, each of the p:when
elements is tested in turn, by evaluating the
expression and converting the resulting object to a boolean as if by a call to the boolean
function. The content of the first, and only the first, p:when
element whose test is true
is instantiated. If no p:when
is true, the content of the p:otherwise
element is
instantiated. If no p:when
element is true, and no p:otherwise
element is present,
nothing is created.
Applies a template to each entries of the provided array.
<p:foreach
in = expression | this
as = qname | this>
<!-- Content: p:with-param*, template -->
</p:foreach>
At each turn the following variables are updated in self
:
count
: The number of entries.position
: The position of the current entry.left
: The number of entries left.even
: "even" if the position is even, an empty string otherwise.key
: The key of the entry.
Binds a name to a value.
<!-- Category: top-level-element -->
<!-- Category: instruction -->
<p:variable
name = qname
select = expression>
<!-- Content: p:with-param*, template? -->
</p:variable>
<!-- Category: top-level-element -->
<p:param
name = qname
select = expression>
<!-- Content: template? -->
</p:param>
The value to which a variable is bound (the value of the variable) can be an object of any
of the types that can be returned by expressions. There are two elements that can be used
to bind variables: p:variable
and p:with-param
. The difference is that the value specified
on the p:with-param
variable is only a default value for the binding; when the template within
which the p:with-param
element occurs is invoked, parameters may be passed that are used in
place of the default values.
Both p:variable
and p:with-param
have a required name attribute, which specifies the
name of the variable. The value of the name attribute is a qualified name.
<p:variable name="count" select="@comments_count" />
<p:variable name="count">There are #{@comments_count} comments</p:variable>
Parses a template with a bounded value.
<p:with
select = expression>
<!-- Content: p:with-param*, template -->
</p:with>
<p:with select="articles.first().comments.last()">
Last comment: <a href="#{@url}">#{@title}</a>
</p:with>
Decorates a content with a template.
<p:decorate
with = string>
<!-- Content: p:with-param*, template -->
</p:decorate>
The content of the markup is rendered to create the component to decorate, it is then passed
to the decorating template as the component
variable.
The name of the decorating template is specified with the with
attribute, and is
interpolated e.g. if "page" is specified the templates "@page.html" or "partials/@page.html"
are used, which ever comes first.
The parameters specified using with-param
, as well as the attribute of the markup (except with
)
are made available as variables in the decorating template.
<p:decorate with="page">
<p:page:content id="body" />
</p:decorate>
The @page.html
template:
<!DOCTYPE html>
<head>
</head>
<body>
#{component=}
</body>
Adds a template.
<p:template
name = qname>
<!-- Content: p:with-param*, template -->
</p:template>
The name
attribute defines the name of the template. The content of the markup defines
the template.
Calls a template.
<p:call-template
name = qname>
<!-- Content: p:with-param* -->
</p:call-template>
Translates and interpolates a string.
<p:translate
native = string>
<!-- Content: p:with-param* -->
</p:translate>
The arguments for the interpolation are provided using the attributes of the markup, or the
with-param
construction.
Example:
<p:translate native="Posted on :date by !name">
<p:with-param name="date"><time datetime="#{@date}" pubdate="pubdate">#{@date.format_date()}</time></p:with-param>
<p:with-param name="name" select="@user.name" />
</p:translate>
CSS assets can be collected and rendered into LINK
elements with the p:document:css
element. The href
attribute is used to add an asset to the collection. The weight
attribute specifies the weight of that asset. If the weight
attribute is not specified,
the weight of the asset is defaulted to 100. If the href
attribute is not specified,
the assets are rendered. If a template is specified the collection is passed as this
,
otherwise the collection is rendered into an HTML string of LINK
elements.
Note: This markup requires the brickrouge/brickrouge package.
<p:document:css
href = string
weight = int>
<!-- Content: p:with-params, template? -->
</p:document:css>
Example:
<p:document:css href="/public/page.css" />
<p:document:css href="/public/reset.css" weight="-100" />
<p:document:css />
will produce:
<link href="/public/reset.css" type="text/css" rel="stylesheet" />
<link href="/public/page.css" type="text/css" rel="stylesheet" />
JavaScript assets can be collected and rendered into SCRIPT
elements with the p:document:js
element. The href
attribute is used to add an asset to the collection. The weight
attribute specifies the weight of that asset. If the weight
attribute is not specified,
the weight of the asset is defaulted to 100. If the href
attribute is not specified,
the assets are rendered. If a template is specified the collection is passed as this
,
otherwise the collection is rendered into an HTML string of SCRIPT
elements.
Note: This markup requires the brickrouge/brickrouge package.
<p:document:js
href = string
weight = int>
<!-- Content: p:with-params, template? -->
</p:document:js>
Example:
<p:document:js href="/public/page.js" />
<p:document:js href="/public/reset.js" weight="-100" />
<p:document:js />
will produce:
<script src="/public/reset.css" type="text/javascript"></script>
<script src="/public/page.css" type="text/javascript"></script>
Renders a page element.
Note: This markup requires the brickrouge/brickrouge package.
<p:pager
count = int
page = int
limit = int
with = string
range = expression
noarrows = boolean>
<!-- Content: p:with-param*, template? -->
</p:pager>
The package requires PHP 5.4 or later.
The recommended way to install this package is through Composer:
$ composer require icybee/patron
The following packages are required, you might want to check them out:
The package is available on GitHub, its repository can be cloned with the following command line:
$ git clone https://github.com/Icybee/Patron.git
You can generate the documentation for the package and its dependencies with the make doc
command. The documentation is generated in the docs
directory. ApiGen is
required. The directory can later be cleaned with the make clean
command.
The test suite is ran with the make test
command. Composer is
automatically installed as well as all dependencies required to run the suite. You can later
clean the directory with the make clean
command.
The package is continuously tested by Travis CI.
This package is licensed under the New BSD License - See the LICENSE file for details.