LightnCandy: Deep Dive Partials

Static Partial

LightnCandy will compile partials as included content by default for better performance.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "\ncode for {{>foo}} just like\ncode for {{{bar}}}";

$phpStr = LightnCandy::compile($template, array(
    'partials' => array(
        'foo' => '{{{bar}}}'
    )
));

echo $phpStr;

Output

return function ($in = null, $options = null) {
    $helpers = array();
    $partials = array();
    $cx = array(
        'flags' => array(
            'jstrue' => false,
            'jsobj' => false,
            'jslen' => false,
            'spvar' => false,
            'prop' => false,
            'method' => false,
            'lambda' => false,
            'mustlok' => false,
            'mustlam' => false,
            'mustsec' => false,
            'echo' => true,
            'partnc' => false,
            'knohlp' => false,
            'debug' => isset($options['debug']) ? $options['debug'] : 1,
        ),
        'constants' =>  array(
            'DEBUG_ERROR_LOG' => 1,
            'DEBUG_ERROR_EXCEPTION' => 2,
            'DEBUG_TAGS' => 4,
            'DEBUG_TAGS_ANSI' => 12,
            'DEBUG_TAGS_HTML' => 20,
        ),
        'helpers' => isset($options['helpers']) ? array_merge($helpers, $options['helpers']) : $helpers,
        'partials' => isset($options['partials']) ? array_merge($partials, $options['partials']) : $partials,
        'scopes' => array(),
        'sp_vars' => isset($options['data']) ? array_merge(array('root' => $in), $options['data']) : array('root' => $in),
        'blparam' => array(),
        'partialid' => 0,
        'runtime' => '\LightnCandy\Runtime',
    );
    
    $inary=is_array($in);
    ob_start();echo '
code for ','',(($inary && isset($in['bar'])) ? $in['bar'] : null),'',' just like
code for ',(($inary && isset($in['bar'])) ? $in['bar'] : null),'';return ob_get_clean();
};

Runtime Partial

With FLAG_RUNTIMEPARTIAL option, partials will be compiled as functions which can handle context change.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "\ncode for {{>foo}} is different to\ncode for {{{bar}}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_RUNTIMEPARTIAL,
    'partials' => array(
        'foo' => '{{{bar}}}'
    )
));

echo $phpStr;

Output

use \LightnCandy\Runtime as LR;return function ($in = null, $options = null) {
    $helpers = array();
    $partials = array('foo' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.(($inary && isset($in['bar'])) ? $in['bar'] : null).'';});
    $cx = array(
        'flags' => array(
            'jstrue' => false,
            'jsobj' => false,
            'jslen' => false,
            'spvar' => false,
            'prop' => false,
            'method' => false,
            'lambda' => false,
            'mustlok' => false,
            'mustlam' => false,
            'mustsec' => false,
            'echo' => false,
            'partnc' => false,
            'knohlp' => false,
            'debug' => isset($options['debug']) ? $options['debug'] : 1,
        ),
        'constants' => array(),
        'helpers' => isset($options['helpers']) ? array_merge($helpers, $options['helpers']) : $helpers,
        'partials' => isset($options['partials']) ? array_merge($partials, $options['partials']) : $partials,
        'scopes' => array(),
        'sp_vars' => isset($options['data']) ? array_merge(array('root' => $in), $options['data']) : array('root' => $in),
        'blparam' => array(),
        'partialid' => 0,
        'runtime' => '\LightnCandy\Runtime',
    );
    
    $inary=is_array($in);
    return '
code for '.LR::p($cx, 'foo', array(array($in),array()),0).' is different to
code for '.(($inary && isset($in['bar'])) ? $in['bar'] : null).'';
};

Partial Usage

Only used partials will be compiled into render function by default.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "{{>foo}}, {{>bar}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_RUNTIMEPARTIAL,
    'partials' => array(
        'foo' => '{{{foo}}}',
        'bar' => '{{{bar}}}',
        'moo' => '{{{moo}}} not used',
        'qoo' => '{{{qoo}}} not in render function',
    )
));

echo $phpStr;

Output

use \LightnCandy\Runtime as LR;return function ($in = null, $options = null) {
    $helpers = array();
    $partials = array('foo' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.(($inary && isset($in['foo'])) ? $in['foo'] : null).'';},
'bar' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.(($inary && isset($in['bar'])) ? $in['bar'] : null).'';});
    $cx = array(
        'flags' => array(
            'jstrue' => false,
            'jsobj' => false,
            'jslen' => false,
            'spvar' => false,
            'prop' => false,
            'method' => false,
            'lambda' => false,
            'mustlok' => false,
            'mustlam' => false,
            'mustsec' => false,
            'echo' => false,
            'partnc' => false,
            'knohlp' => false,
            'debug' => isset($options['debug']) ? $options['debug'] : 1,
        ),
        'constants' => array(),
        'helpers' => isset($options['helpers']) ? array_merge($helpers, $options['helpers']) : $helpers,
        'partials' => isset($options['partials']) ? array_merge($partials, $options['partials']) : $partials,
        'scopes' => array(),
        'sp_vars' => isset($options['data']) ? array_merge(array('root' => $in), $options['data']) : array('root' => $in),
        'blparam' => array(),
        'partialid' => 0,
        'runtime' => '\LightnCandy\Runtime',
    );
    
    $inary=is_array($in);
    return ''.LR::p($cx, 'foo', array(array($in),array()),0).', '.LR::p($cx, 'bar', array(array($in),array()),0).'';
};

Dynamic Partial

When you using dynamic partial in template, all provided partials will be compiled into render function.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "{{>foo}}, {{>(bar)}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_ADVARNAME | LightnCandy::FLAG_RUNTIMEPARTIAL,
    'helpers' => array(
        'bar' => function () {
            return 'bar';
        }
    ),
    'partials' => array(
        'foo' => '{{{foo}}}',
        'bar' => '{{{bar}}}',
        'moo' => '{{{moo}}} not used',
        'qoo' => '{{{qoo}}} in render function',
    )
));

echo $phpStr;

Output

use \LightnCandy\SafeString as SafeString;use \LightnCandy\Runtime as LR;return function ($in = null, $options = null) {
    $helpers = array(            'bar' => function() {
            return 'bar';
        },
);
    $partials = array('foo' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.(($inary && isset($in['foo'])) ? $in['foo'] : null).'';},
'qoo' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.(($inary && isset($in['qoo'])) ? $in['qoo'] : null).' in render function';},
'moo' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.(($inary && isset($in['moo'])) ? $in['moo'] : null).' not used';},
'bar' => function ($cx, $in, $sp) {$inary=is_array($in);return ''.$sp.''.LR::hbch($cx, 'bar', array(array(),array()), 'raw', $in).'';});
    $cx = array(
        'flags' => array(
            'jstrue' => false,
            'jsobj' => false,
            'jslen' => false,
            'spvar' => false,
            'prop' => false,
            'method' => false,
            'lambda' => false,
            'mustlok' => false,
            'mustlam' => false,
            'mustsec' => false,
            'echo' => false,
            'partnc' => false,
            'knohlp' => false,
            'debug' => isset($options['debug']) ? $options['debug'] : 1,
        ),
        'constants' => array(),
        'helpers' => isset($options['helpers']) ? array_merge($helpers, $options['helpers']) : $helpers,
        'partials' => isset($options['partials']) ? array_merge($partials, $options['partials']) : $partials,
        'scopes' => array(),
        'sp_vars' => isset($options['data']) ? array_merge(array('root' => $in), $options['data']) : array('root' => $in),
        'blparam' => array(),
        'partialid' => 0,
        'runtime' => '\LightnCandy\Runtime',
    );
    
    $inary=is_array($in);
    return ''.LR::p($cx, 'foo', array(array($in),array()),0).', '.LR::p($cx, LR::hbch($cx, 'bar', array(array(),array()), 'raw', $in), array(array($in),array()),0).'';
};

Compile Without Partials

With FLAG_ERROR_SKIPPARTIAL option it will not error when you compile without partials. This can reduce the size of render function.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "{{>foo}}, {{>(bar)}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_ADVARNAME | LightnCandy::FLAG_RUNTIMEPARTIAL | LightnCandy::FLAG_ERROR_SKIPPARTIAL,
    'helpers' => array(
        'bar' => function () {
            return 'bar';
        }
    )
));

// Warning: This code will cause 'partial not found' error
echo $phpStr;

Output

use \LightnCandy\SafeString as SafeString;use \LightnCandy\Runtime as LR;return function ($in = null, $options = null) {
    $helpers = array(            'bar' => function() {
            return 'bar';
        },
);
    $partials = array();
    $cx = array(
        'flags' => array(
            'jstrue' => false,
            'jsobj' => false,
            'jslen' => false,
            'spvar' => false,
            'prop' => false,
            'method' => false,
            'lambda' => false,
            'mustlok' => false,
            'mustlam' => false,
            'mustsec' => false,
            'echo' => false,
            'partnc' => false,
            'knohlp' => false,
            'debug' => isset($options['debug']) ? $options['debug'] : 1,
        ),
        'constants' => array(),
        'helpers' => isset($options['helpers']) ? array_merge($helpers, $options['helpers']) : $helpers,
        'partials' => isset($options['partials']) ? array_merge($partials, $options['partials']) : $partials,
        'scopes' => array(),
        'sp_vars' => isset($options['data']) ? array_merge(array('root' => $in), $options['data']) : array('root' => $in),
        'blparam' => array(),
        'partialid' => 0,
        'runtime' => '\LightnCandy\Runtime',
    );
    
    $inary=is_array($in);
    return ''.LR::p($cx, 'foo', array(array($in),array()),0).', '.LR::p($cx, LR::hbch($cx, 'bar', array(array(),array()), 'raw', $in), array(array($in),array()),0).'';
};

Runtime Partials

You can provide more precompiled partials to render functions.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "{{>foo}}, {{>(bar)}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_ADVARNAME | LightnCandy::FLAG_RUNTIMEPARTIAL | LightnCandy::FLAG_ERROR_SKIPPARTIAL,
    'helpers' => array(
        'bar' => function () {
            return 'bar';
        }
    )
));
$renderer = LightnCandy::prepare($phpStr);

// It will be better to precompile partials and store them into files,
// prevent to use LightnCandy::prepare() in production environment.
$partials = array(
    'foo' => LightnCandy::prepare('return ' . LightnCandy::compilePartial('Hello')),
    'bar' => LightnCandy::prepare('return ' . LightnCandy::compilePartial('World')),
);

echo $renderer(null, array(
    'partials' => $partials
));

Output

Hello, World

See Also...