brightnucleus / view
Reusable View component, that can provide different implementations.
Installs: 4 766
Dependents: 8
Suggesters: 0
Security: 0
Stars: 16
Watchers: 3
Forks: 2
Open Issues: 3
Requires
- php: >=8.0
- brightnucleus/config: >=0.5
- brightnucleus/exceptions: >=0.4
- doctrine/collections: >=1.3
- symfony/finder: >=3.1
Requires (Dev)
- malukenho/docheader: ^1
- php-parallel-lint/php-parallel-lint: ^1.4
- phpunit/phpunit: ^7.5 || ^8.5 || ^9.5 || ^10
- squizlabs/php_codesniffer: ^3
- yoast/phpunit-polyfills: ^3
README
This is a reusable View component that can provide different implementations (in separate, optional packages).
Table Of Contents
Installation
The best way to use this component is through Composer:
composer require brightnucleus/view
Basic Usage
The simplest way to use the View
component is through its Facade: BrightNucleus\Views
.
This Facade makes use of a basic BaseView
View implementation as well as a basic PHPEngine
Engine implementation. It can just be used as is and does not need additional configuration.
Adding Locations
You can add locations via the static View::addLocation($location)
method. Each location needs to implement the Location
. The View
component comes with one location provider out of the box: FilesystemLocation
.
Here's how to add a set of folders as a new location:
<?php namespace View\Example; use View\Example\App; use BrightNucleus\View; use BrightNucleus\View\Location\FilesystemLocation; $folders = [ App::ROOT_FOLDER . '/child-theme/templates', App::ROOT_FOLDER . '/parent-theme/templates', App::ROOT_FOLDER . '/plugin/templates', ]; foreach ($folders as $folder) { Views::addLocation(new FilesystemLocation($folder)); }
Rendering A View
To render a view, you pass a view identifier to the static View::render($view, $context, $type)
method.
The $view
is a view identifier that would normally be a template file name, but can also be something else depending on your configured locations & engines.
The $context
array you pass in will be extracted to be available to the template at the time it is rendered.
The $type
argument allows you to inject a specific view/engine combination, instead of letting the View
component find one on its own.
Note: In order for a view to be effectively rendered, it needs to be found amongst one of the locations that were already registered.
Here's how to render a simple view:
<?php namespace View\Example; use View\Example\User; use BrightNucleus\Views; echo Views::render('welcome-user', [ 'userId' => User::getCurrentId() ]);
Context
From within the template that is being rendered, the context variables are available as properties.
As an example, for the view we rendered above, you could use echo $this->userId;
from within the template to retrieve that specific piece of context data.
If you add invokable object to the context as properties, they will in effect act as methods within the view template.
The context as a whole is available through the method $this->getContext()
, which will return an associative array.
Keep in mind that no automatic escaping is taking place, the value of the context data is passed as-is.
Sections
To render a different template as a section from within the template currently being rendered, you can use the $this->section($view, $context, $type)
method.
This does basically the same thing as an external render()
call of a View
object, with the following differences:
- It reuses the parent's
ViewBuilder
, with the same rendering engine, and the same locations. - If you provide additional context, it is merged with the parent's context.
Here's an example of how this works:
<?php namespace View\Example; // This is our template that is being rendered. ?><h1>Welcome screen for User with ID <?= $this->userId ?></h1> <p>This is an example template to show the rendering of partials.</p> <hr> <?= $this->section('user-notifications') ?> <hr> <?= $this->section('user-dashboard') ?>
Advanced Usage
For more advanced use cases, you'll want to provide custom classes for your Views or Engines.
Instantiating A Custom ViewBuilder
To do this, you'll want to create your ViewBuilder
object manually, instead of relying on the Views
Facade. By instantiating it manually, you can provide a custom Config to map your classes.
Once, you've got a ViewBuilder
instance, you can use the addLocation($location)
method to add locations to scan for views and the create($view, $type)
method for creating an actual View. This View can then be rendered through its render($context)
method.
<?php namespace View\Example; use BrightNucleus\Config\ConfigFactory; use BrightNucleus\View\ViewBuilder; use BrightNucleus\View\Location\FilesystemLocation; // Fetch the Config from somewhere. $config = ConfigFactory::create(__DIR__. '/config/views.php'); // Create a new instance of the ViewBuilder and add a location. $viewBuilder = new ViewBuilder( $config ); $viewBuilder->addLocation(new FilesystemLocation(__DIR__ . '/views')); // Create a new instance of a specific View. $view = $viewBuilder->create('my-view'); // Render the view. echo $view->render(['answer' => 42]);
Configuration Schema
Here's an example for providing a custom Config. In this case, we want to replace the default classes with more awesome ones.
<?php namespace View\Example; use BrightNucleus\View\Engine\EngineFinder; use BrightNucleus\View\View\ViewFinder; $engineFinder = [ EngineFinder::CLASS_NAME_KEY => AwesomeEngineFinder::class, EngineFinder::ENGINES_KEY => [ 'AwesomeEngine' => AwesomeEngine::class, ], EngineFinder::NULL_OBJECT => AwesomeNullEngine::class, ]; $viewFinder = [ ViewFinder::CLASS_NAME_KEY => AwesomeViewFinder::class, ViewFinder::VIEWS_KEY => [ 'AwesomeView' => AwesomeView::class, ], ViewFinder::NULL_OBJECT => AwesomeNullView::class, ]; return [ 'BrightNucleus' => [ 'View' => [ 'EngineFinder' => $engineFinder, 'ViewFinder' => $viewFinder, ], ], ];
Of course you don't need to override all of the classes, views or engines. If you only override specific keys, the rest will be taken from the default values.
Contributing
All feedback / bug reports / pull requests are welcome.
License
Copyright (c) 2016-2017 Alain Schlesser, Bright Nucleus
This code is licensed under the MIT License.