PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Aggregating Scripts Using HeadScript

Another common tactic to prevent long page load times is to only load JavaScript when necessary. That said, you may need several layers of scripts: perhaps one for progressively enhancing menus on the site, and another for page-specific content. In these situations, the headScript() helper presents a solution.

Similar to the headLink() helper, headScript() provides the ability to append or prepend scripts to the collection, and then echo the entire set. It provides the flexibility to specify either script files themselves to load, or explicit JavaScript. You also have the option of capturing JavaScript via captureStart()/captureEnd(), which allows you to simply inline the JavaScript instead of requiring an additional call to your server.

Also like headLink(), headScript() provides "virtual" methods via overloading as a convenience when specifying items to aggregate; common methods include prependFile(), appendFile(), prependScript(), and appendScript(). The first two allow you to specify files that will be referenced in a <script> tag's $src attribute; the latter two will take the content provided and render it as literal JavaScript within a <script> tag.

In this example, we'll specify that a script, "/js/site.js" needs to be loaded on every page; we'll update our _initPlaceholders() bootstrap method to do this.

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    // ...

    protected function _initPlaceholders()
    {
        $this->bootstrap('View');
        $view = $this->getResource('View');
        $view->doctype('XHTML1_STRICT');

        // Set the initial title and separator:
        $view->headTitle('My Site')
             ->setSeparator(' :: ');

        // Set the initial stylesheet:
        $view->headLink()->prependStylesheet('/styles/site.css');

        // Set the initial JS to load:
        $view->headScript()->prependFile('/js/site.js');
    }

    // ...
}

Within a view script, we might then add an extra script file to source, or capture some JavaScript to include in our document.


<?php $this->headScript()->appendFile('/js/user-list.js'?>
<?php $this
->headScript()->captureStart() ?>
site = {
    baseUrl: "<?php echo $this->baseUrl() ?>"
};
<?php $this->headScript()->captureEnd() ?>

Within our layout script, we then simply echo the placeholder, just as we have all the others:


<?php echo $this->doctype() ?>
<html>
    <?php echo $this->headTitle() ?>
    <?php echo $this->headLink() ?>
    <?php echo $this->headScript() ?>
    <!-- ... -->

This will generate the following output:


<script type="text/javascript" src="/js/site.js"></script>
<script type="text/javascript" src="/js/user-list.js"></script>
<script type="text/javascript">
site = {
    baseUrl: "<?php echo $this->baseUrl() ?>"
};
</script>

InlineScript Variant

Many browsers will often block display of a page until all scripts and stylesheets referenced in the <head> section have loaded. If you have a number of such directives, this can impact how soon somebody can start actually viewing the page.

One way around this is to emit your <script> tags just prior to closing the <body> of your document. (This is a practice specifically recommend by the Y! Slow project.)

Zend Framework supports this in two different ways:

  • You can render your headScript() tag whereever you like in your layout script; just because the title references "head" does not mean it needs to be rendered in that location.

  • Alternately, you may use the inlineScript() helper, which is simply a variant on headScript(), and retains the same behavior, but uses a separate registry.

Zend Framework