Table Of Contents

Previous topic

< View Helpers

Next topic

Volt: Template Engine >

Assets Management

Phalcon\Assets is a component that allows the developer to manage static resources such as css stylesheets or javascript libraries in a web application.

Phalcon\Assets\Manager is available in the services container, so you can add resources from any part of the application where the container is available.

Adding Resources

Assets supports two built-in resources: css and javascripts. You can create other resources if you need. The assets manager internally stores two default collections of resources one for javascript and another for css.

You can easily add resources to these collections like follows:

<?php

class IndexController extends Phalcon\Mvc\Controller
{
    public function index()
    {

        //Add some local CSS resources
        $this->assets
            ->addCss('css/style.css')
            ->addCss('css/index.css');

        //and some local javascript resources
        $this->assets
            ->addJs('js/jquery.js')
            ->addJs('js/bootstrap.min.js');

    }
}

Then in the views added resources can be printed:

<html>
    <head>
        <title>Some amazing website</title>
        <?php $this->assets->outputCss() ?>
    </head>
    <body>

        <!-- ... -->

        <?php $this->assets->outputJs() ?>
    </body>
<html>

Volt syntax:

<html>
    <head>
        <title>Some amazing website</title>
          {{ assets.outputCss() }}
    </head>
    <body>

        <!-- ... -->

          {{ assets.outputJs() }}
    </body>
<html>

Local/Remote resources

Local resources are those who’re provided by the same application and they’re located in the document root of the application. URLs in local resources are generated by the ‘url’ service, usually Phalcon\Mvc\Url.

Remote resources are those such as common library like jquery, bootstrap, etc. that are provided by a CDN.

<?php

public function indexAction()
{

    //Add some local CSS resources
    $this->assets
        ->addCss('//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css', false)
        ->addCss('css/style.css', true);
}

Collections

Collections groups resources of the same type, the assets manager implicitly creates two collections: css and js. You can create additional collections to group specific resources for ease of placing those resources in the views:

<?php

//Javascripts in the header
$this->assets
    ->collection('header')
    ->addJs('js/jquery.js')
    ->addJs('js/bootstrap.min.js');

//Javascripts in the footer
$this->assets
    ->collection('footer')
    ->addJs('js/jquery.js')
    ->addJs('js/bootstrap.min.js');

Then in the views:

<html>
    <head>
        <title>Some amazing website</title>
        <?php $this->assets->outputJs('header') ?>
    </head>
    <body>

        <!-- ... -->

        <?php $this->assets->outputJs('footer') ?>
    </body>
<html>

Volt syntax:

<html>
    <head>
        <title>Some amazing website</title>
          {{ assets.outputCss('header') }}
    </head>
    <body>

        <!-- ... -->

          {{ assets.outputJs('footer') }}
    </body>
<html>

Prefixes

Collections can be URL-prefixed, this allows to easily change from a server to other at any moment:

<?php

$scripts = $this->assets->collection('footer');

if ($config->environment == 'development') {
    $scripts->setPrefix('/');
} else {
    $scripts->setPrefix('http:://cdn.example.com/');
}

$scripts->addJs('js/jquery.js')
        ->addJs('js/bootstrap.min.js');

A chainable syntax is available too:

<?php

$scripts = $assets
    ->collection('header')
    ->setPrefix('http://cdn.example.com/')
    ->setLocal(false)
    ->addJs('js/jquery.js')
    ->addJs('js/bootstrap.min.js');

Minification/Filtering

Phalcon\Assets provides built-in minification of Javascript and CSS resources. The developer can create a collection of resources instructing the Assets Manager which ones must be filtered and which ones must be left as they are. In addition to the above, Jsmin by Douglas Crockford is part of the core extension offering minification of javascript files for maximum performance. In the CSS land, CSSMin by Ryan Day is also available to minify CSS files:

The following example shows how to minify a collection of resources:

<?php

$manager

    //These Javascripts are located in the page's bottom
    ->collection('jsFooter')

    //The name of the final output
    ->setTargetPath('final.js')

    //The script tag is generated with this URI
    ->setTargetUri('production/final.js')

    //This is a remote resource that does not need filtering
    ->addJs('code.jquery.com/jquery-1.10.0.min.js', true, false)

    //These are local resources that must be filtered
    ->addJs('common-functions.js')
    ->addJs('page-functions.js')

    //Join all the resources in a single file
    ->join(true)

    //Use the built-in Jsmin filter
    ->addFilter(new Phalcon\Assets\Filters\Jsmin())

    //Use a custom filter
    ->addFilter(new MyApp\Assets\Filters\LicenseStamper());

It starts getting a collection of resources from the assets manager, a collection can contain javascript or css resources but not both. Some resources may be remote, that is, they’re obtained by HTTP from a remote source for further filtering. It is recommended to convert the external resources to local eliminating the overhead of obtaining them.

<?php

//These Javascripts are located in the page's bottom
$js = $manager->collection('jsFooter');

As seen above, method addJs is used to add resources to the collection, the second parameter indicates whether the resource is external or not and the third parameter indicates whether the resource should be filtered or left as is:

<?php

// This a remote resource that does not need filtering
$js->addJs('code.jquery.com/jquery-1.10.0.min.js', true, false);

// These are local resources that must be filtered
$js->addJs('common-functions.js');
$js->addJs('page-functions.js');

Filters are registered in the collection, multiple filters are allowed, content in resources are filtered in the same order as filters were registered:

<?php

//Use the built-in Jsmin filter
$js->addFilter(new Phalcon\Assets\Filters\Jsmin());

//Use a custom filter
$js->addFilter(new MyApp\Assets\Filters\LicenseStamper());

Note that both built-in and custom filters can be transparently applied to collections. Last step is decide if all the resources in the collection must be joined in a single file or serve each of them individually. To tell the collection that all resources must be joined you can use the method ‘join’:

<?php

// This a remote resource that does not need filtering
$js->join(true);

//The name of the final file path
$js->setTargetPath('public/production/final.js');

//The script html tag is generated with this URI
$js->setTargetUri('production/final.js');

If resources are going to be joined, we need also to define which file will be used to store the resources and which uri will be used to show it. These settings are set up with setTargetPath() and setTargetUri().

Built-In Filters

Phalcon provides 2 built-in filters to minify both javascript and css respectively, their C-backend provide the minimum overhead to perform this task:

Filter Description
Phalcon\Assets\Filters\Jsmin Minifies Javascript removing unnecessary characters that are ignored by Javascript interpreters/compilers
Phalcon\Assets\Filters\Cssmin Minifies CSS removing unnecessary characters that are already ignored by browsers

Custom Filters

In addition to built-in filters, a developer can create his own filters. These can take advantage of existing and more advanced tools like YUI, Sass, Closure, etc.:

<?php

use Phalcon\Assets\FilterInterface;

/**
 * Filters CSS content using YUI
 *
 * @param string $contents
 * @return string
 */
class CssYUICompressor implements FilterInterface
{

    protected $_options;

    /**
     * CssYUICompressor constructor
     *
     * @param array $options
     */
    public function __construct($options)
    {
        $this->_options = $options;
    }

    /**
     * Do the filtering
     *
     * @param string $contents
     * @return string
     */
    public function filter($contents)
    {

        //Write the string contents into a temporal file
        file_put_contents('temp/my-temp-1.css', $contents);

        system(
            $this->_options['java-bin'] .
            ' -jar ' .
            $this->_options['yui'] .
            ' --type css '.
            'temp/my-temp-file-1.css ' .
            $this->_options['extra-options'] .
            ' -o temp/my-temp-file-2.css'
        );

        //Return the contents of file
        return file_get_contents("temp/my-temp-file-2.css");
    }
}

Usage:

<?php

//Get some CSS collection
$css = $this->assets->get('head');

//Add/Enable the YUI compressor filter in the collection
$css->addFilter(new CssYUICompressor(array(
     'java-bin' => '/usr/local/bin/java',
     'yui' => '/some/path/yuicompressor-x.y.z.jar',
     'extra-options' => '--charset utf8'
)));

Custom Output

Methods outputJs and outputCss are available to generate the necessary HTML code according to each type of resources. You can override this method or print the resources manually in the following way:

<?php

foreach ($this->assets->collection('js') as $resource) {
    echo \Phalcon\Tag::javascriptInclude($resource->getPath());
}