dev-master
9999999-devNamespaced template resolver for templating packages that do not provide one
MIT
The Requires
- php >=5.5
- psr/cache ^1.0
The Development Requires
Wallogit.com
2017 © Pedro Peláez
Namespaced template resolver for templating packages that do not provide one
Namespaced template resolver for templating systems that do not provide one., (*1)
Install via Composer:, (*3)
composer require kynx/template-resolver
The simplest usage is with a single filesystem resolver. This will resolve the content of templates it finds on the
paths you specify. Assuming you have a template engine called MyRenderer:, (*4)
$renderer = new MyRenderer();
$resolver = new FilesystemResolver();
$resolver->addPath('/path/to/templates')
->setExtension('tpl');
$template = $resolver->resolve('test');
echo $renderer->render((string) $template);
// will output the contents of '/path/to/templates/test.tpl'
Namespaces enable you to separate your templates out into distinct search paths:, (*5)
$renderer = new MyRenderer();
$resolver = new FilesystemResolver();
$resolver->addPath('/path/to/templates')
->addPath('/path/to/namespace', 'mynamespace')
->setExtension('tpl');
$template = $resolver->resolve('mynamesapce::test');
echo $renderer->render((string) $template);
// will output the contents of '/path/to/namespace/test.tpl'
The mynamespace::test syntax tells the resolver to first search for the template in the mynamespace path(s). If it is
not found there the default namespace will be searched., (*6)
To speed up subsequent lookups for templates you can store them in any PSR-6
compliant caching engine. The example below uses bravo3/cache. The
AggregateResolver enables you to search the cache for templates first before hitting the filesystem:, (*7)
$resolver = new AggregateResolver();
$cachePool = new RedisCachePool('tcp://10.0.0.1:6379');
$cacheResolver = new CacheResolver($cachePool);
$fileResolver = new FilesystemResolver();
$fileResolver->addPath('/path/to/templates')
->addPath('/path/to/namespace', 'mynamespace')
->setExtension('tpl');
$resolver->accept($cacheResolver, 1);
$resolver->accept($fileResolver, 0);
$result = $resolver->resolve('mynamespace::test');
if (! $result->isCached()) {
// store the result in cache
$resolver->save($result->getKey(), (string) $result);
}
echo (string) $result;
// outputs temple contents
The second argument to AggregateResolver::accept() determines the priority: higher values are searched first, and first
result found is returned. Note that it is up to your implementation to store the result back in the cache., (*8)
Many template systems can compile templates to speed up subsequent processing. The compiled template may be an array of tokens, a PHP function or, as in my own Handlebars implementation, javascript. All of these make an excellent candidate for caching. Extending the above example:, (*9)
// ...
$cacheResolver = new CacheResolver($cachePool);
$cachResolver->setIsCompiled(true);
// ...
$result = $resolver->resolve('mynamesapce::test');
if ($result->isCompiled()) {
$compiled = $result->getContents();
} else {
// compile the result
$compiled = $handlebars->precompile((string) $result);
$resolver->save($result->getKey(), $compiled);
}
// do something with your compiled template
The AggregateResolver will save the result in the first resolver in it's queue that supports the save() method., (*10)
Result objectsAs shown in the examples above, the return value of ResolverInterfae::resolve() is an object with a __toString()
convenience method for accessing the content. Other methods of interest are:, (*11)
getContent(): returns the template content. If your compiled template is an array, use this instead of (string) $result
getKey(): this returns the namespace::template that was actually matched. So if you request mynamespace::test
which does not exist in mynamespace but is found in the default namespace, the key will look something like
__DEFAULT__::test. Using this as the cache key will result in two cache hits for subsequent searches, but will
ensure duplicates are not stored in cache.isCached(): returns true if the content was found in a caching resolverisCompiled(): returns true if the resolver was marked as a compiled resolver via setIsCompiled()
To create other resolvers - for instance, to fetch templates from a DB - implement the ResolverInterface. This contains
only two methods, resolve() and setIsCompiled()., (*12)
If your resolver can handle multiple paths it should implement the PathedResolverInterface, which augments the above
with an addPath() and getPaths() method., (*13)
If your resolver supports saving results back, implement the SavingResolverInterface., (*14)
For convenience there is an AbstractResolver class you can extend, which contains some useful utility methods., (*15)
Much of the inspiration from this, and much of the AggregateResolver code, came from phly-mustache's
template resolver., (*16)
Namespaced template resolver for templating packages that do not provide one
MIT