Giter VIP home page Giter VIP logo

aura.view's Introduction

Aura View

This package provides an implementation of the TemplateView and TwoStepView patterns, with support for helpers and for closures as templates, using PHP itself as the templating language. Template code can be in closures or PHP include files.

It is preceded by systems such as Savant, Zend_View, and Solar_View.

Foreword

Installation

This library requires PHP 5.4 or later, and has no userland dependencies.

It is installable and autoloadable via Composer as aura/view.

Alternatively, download a release or clone this repository, then require or include its autoload.php file.

Quality

Scrutinizer Code Quality Code Coverage Build Status

To run the PHPUnit tests at the command line, go to the tests directory and issue phpunit.

This library attempts to comply with PSR-1, PSR-2, and PSR-4. If you notice compliance oversights, please send a patch via pull request.

Community

To ask questions, provide feedback, or otherwise communicate with the Aura community, please join our Google Group, follow @auraphp on Twitter, or chat with us on #auraphp on Freenode.

Getting Started

Instantiation

To instantiate a View object, use the ViewFactory:

<?php
$view_factory = new \Aura\View\ViewFactory;
$view = $view_factory->newInstance();
?>

Escaping Output

Security-minded observers will note that all the examples in this document use unescaped output. Because this package is not specific to any particular media type, it does not come with escaping functionality.

When you generate output via templates, you must escape it appropriately for security purposes. This means that HTML templates should use HTML escaping, CSS templates should use CSS escaping, XML templates should use XML escaping, PDF templates should use PDF escaping, RTF templates should use RTF escaping, and so on.

For a good set of HTML escapers, please consider Aura.Html.

Registering View Templates

Now that we have a View, we need to add named templates to its view template registry. These can be closures or PHP file paths. For example:

<?php
$view_registry = $view->getViewRegistry();
$view_registry->set('browse', function () {
    echo "The browse view.";
});
$view_registry->set('read', '/path/to/views/read.php');
?>

Note that we use echo, and not return, in closures. Likewise, the PHP file should use echo to generate output.

N.b.: The template logic will be executed inside the View object scope, which means that $this in the template code will refer to the View object. This is true both for closures and for PHP files.

Rendering A One-Step View

Now that we have registered some templates, we tell the View which one we want to use, and then invoke the View:

<?php
$view->setView('browse');
$output = $view();
?>

The $output in this case will be "The browse view."

Setting Data

We will almost always want to use dynamic data in our templates. To assign a data collection to the View, use the setData() method and either an array or an object. We can then use data elements as if they are properties on the View object:

<?php
$view_registry = $view->getViewRegistry();
$view_registry->set('hello', function () {
    echo "Hello {$this->name}!";
});
$view->setData(array('name' => 'World'));
$view->setView('hello');
$output = $view();
?>

N.b.: Recall that $this in the template logic refers to the View object, so that data assigned to the View can be accessed as properties on $this.

The $output in this case will be "Hello World!".

Using Sub-Templates (aka "Partials")

Sometimes we will want to split a template up into multiple pieces. We can render these "partial" template pieces using the render() method in our main template code.

First, we place the sub-template in the view registry (or in the layout regsitry if it for use in layouts). Then we render() it from inside the main template code. Sub-templates can use any naming scheme we like. Some systems use the convention of prefixing partial templates with an underscore, and the following example will use that convention.

Because $this is available in both the main template and sub-template scopes, we need to deconflict any variables specifically for sub-templates with variables intended for the main templates. The following example does so by prefixing sub-template variables with an underscore, but you can choose any convention you like. The example uses the second argument of render() as a convenience to add data to the view.

<?php
// add templates to the view registry
$view_registry = $view->getViewRegistry();

// the "main" template
$view_registry->set('item_rows', function () {
    foreach ($this->items as $item) {
        echo $this->render('_item_row', array(
            '_item' => $item,
        ));
    };
});

// the "sub" (partial) template
$view_registry->set('_item_row', function () {
    echo "The item names '{$this->_item['name']}'' "
       . "costs {$this->_item['price']}" . PHP_EOL
});

// set the data and the view template name
$view->setData(array('items' => array(...));
$view->setView('item_rows');

// execute the view
$output = $view();
?>

Alternatively, we can use include or require to execute a PHP file directly in the current template scope.

Using Sections

Sections are similar to sub-templates (aka "partials") except that they are captured inline for later use. In general, they are used by view templates to capture output for layout templates.

For example, we can capture output in the view template to a named section ...

<?php
// begin buffering output for a named section
$this->beginSection('local-nav');

echo "<div>";
// ... echo the local navigation output ...
echo "</div>";

// end buffering and capture the output
$this->endSection();
?>

... and then use that output in a layout template:

<?php
if ($this->hasSection('local-nav')) {
    echo $this->getSection('local-nav');
} else {
    echo "<div>No local navigation.</div>";
}
?>

In addition, the setSection() method can be used to set the section body directly, instead of capturing it:

<?php
$this->setSection('local-nav', $this->render('_local-nav.php'));
?>

Using Helpers

The ViewFactory instantiates the View with an empty HelperRegistry to manage helpers. We can register closures or other invokable objects as helpers through the HelperRegistry. We can then call these helpers as if they are methods on the View.

<?php
$helpers = $view->getHelpers();
$helpers->set('hello', function ($name) {
    return "Hello {$name}!";
});

$view_registry = $view->getViewRegistry();
$view_registry->set('index', function () {
    echo $this->hello('World');
});

$view->setView('index');
$output = $view();
?>

This library does not come with any view helpers. You will need to add your own helpers to the registry as closures or invokable objects.

Custom Helper Managers

The View is not type-hinted to any particular class for its helper manager. This means you may inject an arbitrary object of your own at View construction time to manage helpers. To do so, pass a helper manager of your own to the ViewFactory.

<?php
class OtherHelperManager
{
    public function __call($helper_name, $args)
    {
        // logic to call $helper_name with
        // $args and return the result
    }
}

$helpers = new OtherHelperManager;
$view = $view_factory->newInstance($helpers);
?>

For a comprehensive set of HTML helpers, including form and input helpers, please consider the Aura.Html package and its HelperLocator as an alternative to the HelperRegistry in this package. You can pass it to the ViewFactory like so:

<?php
$helpers_factory = new Aura\Html\HelperLocatorFactory;
$helpers = $helpers_factory->newInstance();
$view = $view_factory->newInstance($helpers);
?>

Rendering a Two-Step View

To wrap the main content in a layout as part of a two-step view, we register layout templates with the View and then call setLayout() to pick one of them for the second step. (If no layout is set, the second step will not be executed.)

<?php
$view_registry = $view->getViewRegistry();
$view_registry->set('main', function () {
    echo "This is the main content." . PHP_EOL;
});

$layout_registry = $view->getLayoutRegistry();
$layout_registry->set('wrapper', function () {
    echo "Before the main content." . PHP_EOL;
    echo $this->getContent();
    echo "After the main content." . PHP_EOL;
})

$view->setView('main_content');
$view->setLayout('wrapper');
$output = $view();
?>

The output from the view template is automatically retained and becomes available via the getContent() method. We can also call setLayout() from inside the view template, allowing us to pick a layout as part of the view logic.

All template dats is shared between the view and the layout. Any data values assigned to the view, or modified by the view, are used as-is by the layout.

Similarly, all helpers are shared between the view and the layout. This sharing situation allows the view to modify data and helpers before the layout is executed.

Finally, all section bodies are shared between the view and the layout. A section that is captured from the view template can therefore be used by the layout template.

aura.view's People

Contributors

harikt avatar ammmze avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.