Installation
You can simple install it by composer, require PHP 5.3 or higher:
composer require undercloud/antUsage
Setup
First step - initialize and setup engine:
require 'vendor/autoload.php';
use Ant\Ant;
//setup instance
Ant::init()
->setup([
/* define root directory of your templates */
'view' => '/path/to/view',
/* define cache directory for compiled templates */
'cache' => '/path/to/cache',
/* define logic path, default empty */
'logic' => '/path/to/logic',
/* you can define your own template extension, default *.ant */
'extension' => 'mytmpl',
/* ignore caching, if option equal true, default false */
'debug' => true,
/* if equal true - ignore rendering and always
try load from cache, use in production for better performance,
default false */
'freeze' => true
]);
Basic
Simple usage example:
require 'vendor/autoload.php';
use Ant\Ant;
echo Ant::init()
->get('index')
->assign([
'title' => "Hello, I'm ANT",
'features' => [
'simple',
'flexible',
'awesome'
]
])
->draw();
Create template:
// index.ant
<html>
<head>
<title>{{ $title }}</title>
</head>
<body>
List of features
<ul>
@foreach ($features as $item)
<li>{{ $item }}</li>
@endforeach
</ul>
</body>
</html>
Project Structure
We recommend use the next folders structure:
views/ ├── header.ant ├── content/ │ ├── about.ant │ ├── news.ant │ ├── products/ │ │ ├── search.ant │ │ └── list.ant │ ├── contacts.ant │ └── suport.ant ├── index.ant ├── menu.ant └── footer.ant
Use nested folders for emulating namespaces, for folders and template name use lowercase symbols a...z and dash -. Don't use a dot . because it will be transformed into invalid path.
For resolve template path ANT use dot.notation.
// will be transformed into /content/products/list.ant
Ant::init()->get('content.products.list')
Events
Here next types of events can be triggered:
- build - before template parse
- prepare - after parse
- exec - after rendering
For cancel event bubbling use preventParentEvent method.
//global events
$ant = Ant::init()->setup([/*...*/]);
$eid = $ant->bind('build', function ($s) { /*...*/ });
$eid = $ant->bind('prepare', function ($s) { /*...*/ });
$eid = $ant->bind('exec', function ($s) { /*...*/ });
//unbind event
$ant->unbind($eid);
//local events
$ant = Ant::init();
$ant->get('template');
$ant->assign($data);
$eid = $ant->on('build', function ($s) { /*...*/ });
$eid = $ant->on('prepare', function ($s) { /*...*/ });
$eid = $ant->on('exec', function ($s) { /*...*/ });
//unbind local event
$ant->off($eid);
//cancel global event
$ant->preventParentEvent($event);
$ant->draw();
Logic
Logic - special layer between model and
view in classic MVC pattern.
Logic layer process variables and pass it to template. If logic path is
defined, use folder structure same as view:
views/ │ ├──path/ │ │ ├──to/ │ │ │ ├──... └── └── └── └──template.ant logic/ │ ├──path/ │ │ ├──to/ │ │ │ ├──... └── └── └── └──template.php
If logic file is exists, ANT include and process it.
Another way use logic - define logic path manually:
echo Ant::init()
->get('template')
->logic($path)
->assign([
'date' => '2002-05-04',
'name' => 'john',
'size' => 45654321
])
->draw();
// /logic/path/to/template.php
$date = $this->date($date, 'd/m/Y');
$name = $this->capitalize($name);
$size = $this->bytesHuman($size);
Extends
You can define your own template syntax:
Ant::init()
...
->rule($rx, $call)
For example we define comments syntax like {!-- ... --!} that will be transformed into <!-- ... -->.
Ant::init()
...
->rule('~{!--.+?--!}/ms~', function($e) {
return '<!-- ' . $e[0] . '-->';
})
API
Complete list of API:
class Ant
{
/*
* Create new instance
*/
function init();
/*
* Return settings params, if $name = false - return all
*
* @param string $name - settings name
*/
function settings($name = false);
/*
* Check template exists
*
* @param string $name - template name
*/
function has($name);
/*
* Select template
*
* @param string $name - template name
*/
function get($name);
/*
* Load template from string
*
* @param string $s - template string
*/
function fromString($s);
/*
* Load template from file
*
* @param string $path - path to template file
*/
function fromFile($path);
/**
* Accept template variables
*
* @param array $data - variables
*/
function assign(array $data = array());
/**
* Render template
*/
function draw();
/*
* Helper wrapper for Ant::init()->get()->assign()->draw()
*
* @param string $path - template name
*/
function view($name);
/*
* @param string $path - path to template
* @param array $assign - variables
*/
function view($name, array $assign);
/*
* @param string $path - path to template
* @param string $logic - path to logic file
*/
function view($name, $logic);
/*
* @param string $path - path to template
* @param array $assign - variables
* @param string $logic - path to logic file
*/
function view($name, array $assign, $logic);
}
Variables
Define template variable by double curly brackets, by default ANT escape all variables:
{{ $name }}
If you don't wanna escape value, use 3 curly brackets syntax:
{{{ $name }}}
Handle empty values:
{{ $name or 'Default' }}
Array values can be accessed by dot notation syntax:
{{ $array.dot.notation }}
Object values can be accessed by arrows:
{{ $objects->arrow->notaion }}
Simple access to global variables:
// $_GET['name']
{{ $.get.name }}
// $_SERVER['DOCUMENT_ROOT']
{{ $.server.DOCUMENT_ROOT }}
// $GLOBALS['foo']
{{ $.globals.foo }}
// shortcut helper
{{ $.ant }}
$.scope - special variable that contains all defined variables in scope:
@each('view.path', $comments, 'com', $.scope)
@import('view.path', $.scope)
Easy plugin access:
$.plugin->youtube('6v2L2UGZJAM')
Comment syntax:
{{-- comments never output --}}
For skipping variable parsing use single backslash, now you can safely use Angular variables:
<div>
<label>Name:</label>
<input type="text" ng-model="yourName" placeholder="Enter a name here">
<hr>
<h1>Hello \{{yourName}}!</h1>
</div>
Control
@if
@if ($condition)
<div>Block One</div>
@elseif ($alter)
<div>Block Two</div>
@else
<div>Block Three</div>
@endif
@unless
@unless ($is_mobile)
<div>You use desktop version</div>
@endunless
@switch
@switch ($fruit)
@case ('apple')
<img src="apple.png" />
@break
@case ('pear')
<img src="pear.png" />
@break
@default
<img src="no-image.png" />
@break
@endswitch
@for
<ul>
@for ($i = 0; $i < 10; $i++)
<li>{{ $i }}</li>
@endfor
</ul>
@while
@while ($condition)
...
@endwhile
@foreach
@foreach ($comments as $com)
<div class="comment-item">
<div class="comment-date">{{ $com.date }}</div>
<div class="comment-text">{{ $com.text }}</div>
</div>
@endforeach
Inside @foreach and @forelse loops you can get iterator state, ANT wrap collection by Ant\StateIterator and restore value after loop is end.
@foreach ($collection as $item)
// check first iteration
@if ($collection->isFirst())
...
// check last iteration
@if ($collection->isLast())
...
// is between first and last
@if ($collection->isMiddle())
...
// is iteration number is odd
@if ($collection->isOdd())
...
// is iteration number is even
@if ($collection->isEven())
...
// is iteration number divisible by number
@if ($collection->isDivisible($by))
...
@endforeach
@forelse
@forelse ($comments as $com)
...
@empty
<div>No comments yet :(</div>
@endforelse
@each
@each ('view.path', $comments, 'com')
...
//view.path
<div class="comment-item">
<div class="comment-date">{{ $com.date }}</div>
<div class="comment-text">{{ $com.text }}</div>
</div>
@each($view, $collection[,$item[,$scope]])
- $view - template name
- $collection - data
- $item - variable name, default item
- $scope - additional data
@import
Shortcut to Ant::view.
<!DOCTYPE html>
<html>
<head>
<title>Include Blocks</title>
</head>
<body>
@import ('header')
...
@import ('content')
...
@import ('footer')
</body>
</html>
@widget
Equivalent to @import.
@skip
For ignore parsing use @skip tag.
@skip
{{ $vaiable }}
@endskip
@php
@php
// multiline php code
...
@endphp
Inheritance
Define base layout:
// layout.ant
<!DOCTYPE html>
<html>
<head>
<title>Inheritance Example</title>
@block('scripts')
@js('/path/to/script.js')
@endblock
@block('styles')
@css('/path/to/style.css')
@endblock
</head>
<body>
@block('contents')
<main>Content will be replaced</main>
@endblock
</body>
</html>
Extends:
// inject.ant
@extends('layout')
@inject('scripts')
@js('/path/to/another.js')
@append
@inject('styles')
@css('/path/to/another.css')
@prepend
@inject('contents')
<main>Contents</main>
@rewrite
Final page:
<!DOCTYPE html>
<html>
<head>
<title>Inheritance Example</title>
<script type="text/javascript" src="/path/to/script.js"></script>
<script type="text/javascript" src="/path/to/another.js"></script>
<link type="text/css" rel="stylesheet" href="/path/to/another.css" />
<link type="text/css" rel="stylesheet" href="/path/to/style.css" />
</head>
<body>
<main>Contents</main>
</body>
Functions
For calling defined functions use next syntax:
//short syntax
{{ ::functionName($param) }}
//long syntax
{{ $this->ant->functionName($param) }}
For creating new function use Ant::share.
//define function
Ant::share('pow', function($n) {
return $n * $n;
});
//check function exists
Ant::isShared('pow')
//call
{{ ::pow(5) }}
doctype
doctype($type = 'HTML5')
Description
Return DOCTYPE declaration
Parameters
- $type
- One of values
- HTML5
- XHTML11
- XHTML1_STRICT
- XHTML1_TRANSITIONAL
- XHTML1_FRAMESET
- XHTML_liASIC1
- HTML4_STRICT
- HTML4_LOOSE
- HTML4_FRAMESET
js
js($src, $defer = "")
// or you can use shortcut
@js($src, $defer = "")
Description
Embed script
Parameters
- $src
- Path to script
- $defer
- Additional attributes: defer or async
css
css($href, $media = "")
//or you can use shortcut
@css($href, $media = "")
Description
Embed style
Parameters
- $href
- Path to stylesheet
- $media
- Media values
escape
escape($string, $double = false)
Description
Escape string
Parameters
- $string
- The input string
- $double
- Process escaped entity, default false
decode
decode($string)
Description
Unescape string
Parameters
- $string
- The input string
upper
//hello => HELLO
upper($string)
Description
Make a string uppercase
Parameters
- $string
- The input string
lower
// HELLO => hello
lower($string)
Description
Make a string lowercase
Parameters
- $string
- The input string
isBlank
isBlank($what)
Description
Return true if variable is null, false, empty string, string with whitespaces only, or empty array
Parameters
- $what
- Variable for check
isEmpty
isEmpty($what)
Description
Return true if variable is 0, null, false, empty string, string with whitespaces only, or empty array
Parameters
- $what
- Variable for check
date
date($date, $format = 'Y-m-d H:i:s', $tz = null)
Description
Print date in given format
Parameters
- $date
- Date value accepted by DateTime
- $format
- Output format
- $tz
- Timezone name
capitalize
// hello => Hello
capitalize($string)
Description
Capitalize string
Parameters
- $string
- The input string
capitalizeAll
// hello world => Hello World
capitalizeAll($string)
Description
Capitalize all words in string
Parameters
- $string
- The input string
whitespace
// H el lo => H el lo
whitespace($string)
Description
Replaces all white-space characters sequence, with single white-space
Parameters
- $string
- The input string
limit
// Lorem ipsum dolor sit amet, cons...
limit($string, $limit = 250, $postfix = '...')
Description
Limit string length
Parameters
- $string
- The input string
- $limit
- Number of characters
- $postfix
- String decorator
limitWords
// Lorem ipsum dolor sit amet, consectetuer...
limitWords($string, $limit = 250, $postfix = '...')
Description
Limit string length, non word breaking
Parameters
- $string
- The input string
- $limit
- Number of characters
- $postfix
- String decorator
limitMiddle
// Lorem ipsum dolor...te feugait nulla facilisi.
limitMiddle($string, $limit = 250, $postfix = '...')
Description
Limit string length, by middle
Parameters
- $string
- The input string
- $limit
- Number of characters
- $postfix
- String decorator
lorem
// Lorem ipsum dolor sit amet, consectetuer
lorem($limit = 544)
Description
Fake text generator
Parameters
- $limit
- Fake text length
number
// 3548791 => 3 548 791
number($num, $precision = 0)
Description
Format number
Parameters
- $num
- Number
- $precision
- Precision
bytesHuman
// 4637467 => 4.42 MB
bytesHuman($size, $precision = 2)
Description
Human readable in bytes
Parameters
- $size
- Size in bytes
- $precision
- Precision
roundHuman
// 637467 => 637.47 K
roundHuman($size, $precision = 2)
Description
Format number
Parameters
- $size
- Number
- $precision
- Precision
ordinal
// 25 => 25th
ordinal($num)
Description
Create ordinal number
Parameters
- $num
- Number
unicode
// I \u2665 HTML => I ♥ HTML
unicode($string)
Description
Conver unicode sequence to html entity
Parameters
- $string
- Sequence
url
// ['foo' => 'bar', 'baz' => 'quux'] => foo=bar&baz=quux
url(array $params)
Description
Build url string
Parameters
- $params
- Params
iterable
iterable($instance)
Description
Check if variable can be used in loops
Parameters
- $instance
- Variable to check
count
count($instance)
Description
Count collection items
Parameters
- $instance
- Variable to check
template
template($tmpl, $params...)
//ANT is simple, flexible and awesome
template('ANT is {1}, {2} and {3}', 'simple', 'flexible', 'awesome')
Description
Build template with placeholders
Parameters
- $tmpl
- Template string
- $params
- Params list
Plugins
ANT provide access for dozen build-in plugins. For activate it use next example:
use Ant\Ant;
// activate plugin
$ant = Ant::init()
->setup([
...
])
->activate($pluginOne)
->activate($pluginTwo)
->activate($pluginThree);
// check is plugin activated
$ant->isActivated($plugin)
// deactivate plugin
$ant->deactivate($plugin)
You can simple define your own plugin like this:
// plugin definition
class MyPlugin
{
public function __construct(array $options)
{
/*...*/
}
public function __invoke($param)
{
/*...*/
}
public function methodName($param)
{
/*...*/
}
}
// global init
Ant::init()
->setup([
...
])
->register('myplugin', new MyPlugin($options));
// call __invoke
{{ $.plugin->myplugin($param) }}
// call methodName
{{ $.plugin->myplugin->methodName($param) }}
Asset
Append file modification time to given path, useful for cache manage. If plugin activated, automatically process path in ::js and ::css functions.
$ant->activate('Asset')
// /path/to/script.js?1463545199
{{ $.plugin->asset($path) }}
// <script src="/path/to/script.js?1463545199"></script>
@js($path)
Compressor
Compress HTML code.
$ant->activate('Compressor')
Faker
Wrapper for https://github.com/fzaninotto/Faker.
You need install it by composer require fzaninotto/faker.
$ant->activate('Faker', ['locale' => 'en_US'])
// 'Lucy Cechtelar'
{{ $.plugin->faker->name }}
Google Analytics
Embed Google Analytics script https://www.google.com/analytics.
$ant->activate('GoogleAnalytics')
{{{ $.plugins->ga($code, $domain = '') }}}
Haml
Haml parser. You need install it by composer require hamlphp/hamlphp.
$ant->activate('Haml')
InlineCSS
Wrapper for InlineCss. You need install it by composer require undercloud/inlinecss.
$ant->activate('InlineCSS')
{{ $.plugin->css(['color' => 'red', 'font-weight' => 'bold']) }}
Jade
Jade parser. You need install it by composer require undercloud/picojade.
$ant->activate('Jade')
Lang
Wrapper for Lang. You need install it by composer require undercloud/lang.
$ant->activate('Lang'[,$options])
// you can use $.lang shortcut helper
{{ $.lang('message.name') }}
Leaf
Wrapper for Leaf. You need install it by composer require undercloud/leaf.
$ant->activate('Leaf')
Markdown
Markdown parser. Port for parsedown. You need install it by composer require erusev/parsedown.
$ant->activate('Markdown')
Validator
HTML validator and linter.
// basic validator, check DOM tree only
$ant->activate('Validator')
// strict, check deprecated tags and attrs, non standard tags, required attrs etc...
$ant->activate('Validator', ['strict' => true])
YouTube
Embed Youtube video.
$ant->activate('YouTube')
// extended setup
$ant->activate('YouTube', ['params' => [...], 'attrs' => [...]])
// embed video
{{{ $.plugin->youtube($video_id[,$options]) }}}
// get preview image url, $size - one of values: hq, mq, sd, maxres or empty for default
{{ $.plugin->youtube->preview($video_id[,$size]) }}