View Basics
Table of Contents
Introduction
Views are the interfaces displayed to your users. Opulence allows you to create your views using native PHP, the Fortune compiler (Opulence's own view engine), or any view engine of your choice.
Views
Views implement Opulence\Views\IView
. They are objects that contain the uncompiled contents of the view, the path to the raw view file, and any variables set in the view. Opulence\Views\View
implements IView
and comes built-in.
Variables
Let's say you would like to output a user's name in your template:
View.php
Hello, <?php echo $user->getName(); ?>
You can set the $user
variable in your controller using
$view->setVar('user', new User('Dave'));
When the view gets compiled, you'll see
Hello, Dave
You can also set many variables using
$view->setVars(['foo' => 'bar', 'baz' => 'blah']);
Compilers
Compilers are what turn your raw views into valid markup, such as HTML and XML. They must implement Opulence\Views\Compilers\ICompiler
, which only has a single method - compile()
.
Registering Compilers
Opulence's compiler looks at a view's file extension to determine which compiler to use. For example, if a view file is named foo.php, the PHP compiler will be used. Likewise, if a view file is named bar.fortune.php
, the Fortune compiler will be used. You can register a compiler for a particular extension using ICompilerRegistry::registerCompiler()
:
use Opulence\Views\Compilers\CompilerRegistry;
$registry = new CompilerRegistry();
$registry->registerCompiler('my-extension', new MyCompiler());
Now, files with extension my-extension
will be compiled by MyCompiler
. If you are using the skeleton project, a good place to register compilers would be in bootstrapper.
Note: If you use the skeleton project, the PHP and Fortune compilers are already registered to the compiler registry.
PHP Compiler
If your views only use native PHP, name them with the php
file extension, eg MyView.php. You can still set and use variables in views when using the PHP compiler:
View.php
<?php echo $foo; ?>
Application Code
$view->setVar('foo', 'bar');
The PHP compiler will compile this to bar
.
Fortune Compiler
Fortune is Opulence's powerful built-in view engine. To use Fortune, name your view file with the fortune or fortune.php file extensions, eg MyView.fortune or MyView.fortune.php. To learn more about Fortune, read the documentation on it.
Factories
Factories simplify the way you create View
objects from view files.
Registering Resolvers
The view factory allows you to create a view using nothing but the filename (no path or extension). It does this using a file name resolver. You register the path where all view files reside as well as the possible file extensions views may have. Then, the resolver finds the raw view file, creates a View
object from its contents, and returns it.
use Opulence\Views\Factories\IO\FileViewNameResolver;
$resolver = new FileViewNameResolver();
$resolver->registerPath('/var/www/html/views/some-directory');
// Register another path that has a priority, which means it will be searched first
$resolver->registerPath('/var/www/html/views/another-directory', 1);
// Register an extension
$resolver->registerExtension('php');
// Register another extension with a priority, which means it will be searched for first
$resolver->registerExtension('fortune', 1);
Note: If you use the skeleton project, the php, fortune, and fortune.php extensions are already registered to the resolver.
View Readers
Opulence uses an Opulence\Views\Factories\IO\IViewReader
to actually read raw views in factories. By default, the FileViewReader
is used to read views stored in the file system, but you can use any storage system you'd like. Simply implement IViewReader
and bind your reader to the IoC container:
$container->bindInstance(IViewReader::class, new MyViewReader());
Creating Views
The easiest way to create views is to pass a ViewFactory
into the controller:
use DateTime;
use Opulence\Http\Responses\Response;
use Opulence\Views\Compilers\ICompiler;
use Opulence\Views\Factories\IViewFactory;
class MyController
{
private $viewCompiler = null;
private $viewFactory = null;
public function __construct(ICompiler $viewCompiler, IViewFactory $viewFactory)
{
$this->viewCompiler = $viewCompiler;
$this->viewFactory = $viewFactory;
}
public function showHomepage() : Response
{
// The view factory will search for a file named "Home" in the registered paths
// with any of the registered extensions
$view = $this->viewFactory->createView('Home');
$view->setVar('now', new DateTime());
return new Response($this->viewCompiler->compile($view));
}
}
Builders
Your views will often need variables to be set whenever they're instantiated. Ideally, this repetitive task should not be done in controllers. Instead, you can use IViewFactory::registerBuilder()
to register a view builder to be run every time a particular view is created. The first parameter is the name of the view you're registering for. The second parameter is a closure that accepts an Opulence\Views\IView
object and returns a built IView
object.
$factory->registerBuilder('Homepage', function ($view) {
$view->setVar('title', 'Welcome!');
return $view;
});
echo $factory->createView('Homepage')->getVar('title'); // "Welcome!"
Note: You can register as many builders as you'd like to a view. They will be run in the order they're registered.
You can also wrap the builder into any class that you'd like:
use Project\Application\Http\Views\Builders\ProfileViewBuilder;
$factory->registerBuilder('Profile', function ($view) {
return (new ProfileViewBuilder())->build($view);
});
Note For convenience, Opulence provides the
Opulence\Views\Factories\IViewBuilder
interface for view builder classes. It contains a single methodbuild()
where your building can take place. However, you are not required to useIViewBuilder
. You can use any class you'd like.
Caching
To improve the speed of view compilers, views are cached using a class that implements Opulence\Views\Caching\ICache
(Opulence\Views\Caching\FileCache
comes built-in to Opulence). You can specify how long a view should live in cache using setLifetime()
. If you do not want views to live in cache at all, you can specify a non-positive lifetime.
Garbage Collection
Occasionally, you should clear out old cached view files to save disk space. If you'd like to call it explicitly, call gc()
on your cache object. FileCache
has a mechanism for performing this garbage collection every so often. You can customize how frequently garbage collection is run:
use Opulence\Views\Caching\FileCache;
// Make 123 out of every 1,000 view compilations trigger garbage collection
$cache = new FileCache('/tmp', 123, 1000);
Or use setGCChance()
:
// Make 1 out of every 500 view compilations trigger garbage collection
$cache->setGCChance(1, 500);