42.4. Помощники видов

Часто бывает так, что в скриптах вида необходимо повторно выполнять определенный набор функций; например, формирование даты, генерация элементов формы, отображение ссылок. Вы можете использовать помощников (вспомогательные классы) для выполнения этих действий.

Помощник представляет собой просто класс. Скажем, нам нужен помощник 'fooBar'. По умолчанию имя класса помощника начинается с 'Zend_View_Helper_' (вы можете указать другой префикс при установке путей к помощникам видов), последней частью имени класа является имя помощника. Все слова этой части должны писаться слитно, первые буквы слов - в верхнем регистре (TitleCapped); таким образом мы получаем имя класа Zend_View_Helper_FooBar. Класс должен содержать как минимум один метод, названный по имени помощника в формате camelCase: fooBar().

[Замечание] Следите за регистром

Имена помощников всегда должны быть в формате camelCase, т.е. они никогда не начинаются с символа в верхнем регистре. Имя для класса начинается с символа в верхнем регистре, но реально выполняемый метод должен быть в формате camelCase.

[Замечание] Путь к помощникам по умолчанию

Используемый по умолчанию путь к помощникам всегда указывает на помощники Zend Framework-а, т.е. 'Zend/View/Helper/'. Даже если вы вызываете setHelperPath() для перезаписи существующих путей, этот путь всегда будет использоваться для обеспечения работы помощников, входящих в поставку Zend Framework-а

Для того, чтобы использовать помощника в своем скрипте вида, вызывайте его, используя $this->имяПомощника(). Zend_View внутри себя загрузит класс Zend_View_Helper_ИмяПомощника, создаст его экземпляр и вызовет его метод имяПомощника(). Экземпляр объекта сохраняется в экземпляре Zend_View и будет повторно использоваться им во всех будущих вызовах $this->имяПомощника().

42.4.1. Начальный набор помощников

Zend_View поставляется с начальным набором помощников, большинство из которых связано с генерацией элементов форм и автоматически экранирует весь вывод. Кроме этого, есть помощники для создания HTML-списков, URL-ов на основе маршрутов, и объявления переменных. В настоящее время в поставляемый набор входят:

  • declareVars(): В основном для использования вместе с strictVars(). Этот помощник может использоваться для объявления переменных шаблонов, которые могут быть или не быть в объекте вида, и для установки значений по умолчанию. Массивы, переданные методу в качестве аргуметов, будут использованы для установки значений по умолчанию; иначе, если переменная не существует, то ее значением будет пустая строка.

  • fieldset($name, $content, $attribs): Создает XHTML-элемент fieldset (набор полей). Если массив $attribs содержит в ключ 'legend', то это значение используется для элемента legend. Элемент fieldset будет содержать в себе значение параметра $content, переданного помощнику.

  • form($name, $attribs, $content): Генерирует XHTML-элемент form (форма). Все элементы массива $attribs и добавляются как аттрибуты тега form. Если параметр $content передан и не имеет значение false, то это содержимое добавляется между открывающим и закрывающим тегами формы. Если же $content имеет булево значение false (по умолчанию), то будет сгенерирован только открывающий тег формы.

  • formButton($name, $value, $attribs): Создает элемент <input type="button" />.

  • formCheckbox($name, $value, $attribs, $options): Создает элемент <input type="checkbox" /> (флажок опций). Параметр $options является массивом, в котором первым значением является "выбранное" (checked) значение, вторым — "невыбранное" значение (по умолчанию это '1' и '0'). Если $value соответствует "выбранному" значению, то этот флажок опций будет выбран.

  • formErrors($errors, $options): Генерирует ненумерованный список XHTML для вывода сообщений об ошибках. $errors должен быть строкой или массивом строк. $options должен заключать в себе все аттрибуты, которые вы хотите поместить в открывающий тег списка.

    Вы можете указать альтернативный открывающий, закрывающий и разделяющий код путем вызова нескольких методов данного помощника:

    • setElementStart($string); по умолчанию используется '<ul class="errors"%s"><li>', где %s заменяется аттрибутами, указанными в $options.

    • setElementSeparator($string); по умолчанию используется '</li><li>'.

    • setElementEnd($string); по умолчанию используется '</li></ul>'.

  • formFile($name, $value, $attribs): Создает элемент <input type="file" />.

  • formHidden($name, $value, $attribs): Создает элемент <input type="hidden" />.

  • formLabel($name, $value, $attribs): Создает элемент <label>, устанавливая значение аттрибута for равным значению $name, и содержимое элемента равным значению $value. Если в $attribs был передан disable, то ничего не будет возвращено.

  • formMultiCheckbox($name, $value, $attribs, $options, $listsep): Создает список флажков опций. $options должен быть ассоциативным массивом, который может быть произвольной глубины. $value может быть скалярным значением или массивом выбранных значений, которые соответствуют ключам в массиве $options. $listsep по умолчанию является переносом строки в HTML ("<br />"). По умолчанию этот элемент интерпретируется как массив - все флажки опций имеют одно и то же имя и передаются как массив.

  • formPassword($name, $value, $attribs): Создает элемент <input type="password" />.

  • formRadio($name, $value, $attribs, $options): Создает последовательность элементов <input type="radio" /> (переключатель опций). В массиве $options ключ является значением переключателя, значение является содержимым элемента label к переключателю. Переключатель опций со значением $value будет предварительно выбранным.

  • formReset($name, $value, $attribs): Создает элемент <input type="password" />.

  • formSelect($name, $value, $attribs, $options): Создает блок <select>...</select>, с опциями <option>, соотвествующими элементам массива $options. В массиве $options ключ является значением опции, значение - текстом опции. Опция со значением $value будет предварительно выбранной.

  • formSubmit($name, $value, $attribs): Создает элемент <input type="submit" />.

  • formText($name, $value, $attribs): Создает элемент <input type="text" />.

  • formTextarea($name, $value, $attribs): Создает блок <textarea>...</textarea>.

  • url($urlOptions, $name, $reset): Создает строку URL, основываясь на машруте с именем $name. $urlOptions должен быть ассоциативным массивом пар ключ-значение для использования в данном маршруте.

  • htmlList($items, $ordered, $attribs, $escape): Генерирует маркированный или нумерованный список на основе $items. Если $items является многомерным массивом, то будут построены вложенные списки. Если $escape установлен в true (значение по умолчанию), то все пункты будут экранированы с использованием механизма, зарегистрированного в объекте вида. Передавайте значение false, если хотите использовать разметку в своих списках. Если $ordered установлен в false (значение по умолчанию), то генерируется маркированный список, иначе - нумерованный.

Использовать их в скрипте вида очень просто, вот пример. Обратите внимание, что это все, что вам нужно для их вызова — помощники будут загружаться и инстанцироваться автоматически, по мере необходимости.

<?php
// в скрипте вида $this ссылается на экземпляр Zend_View
//
// предположим, вы уже имеете последовательность опций $countries
// в виде массива ('us' => 'United States', 'il' =>
// 'Israel', 'de' => 'Germany')
?>
<form action="action.php" method="post">
    <p><label>Your Email:
        <?php echo $this->formText('email', 'you@example.com', array('size' => 32)) ?>
    </label></p>
    <p><label>Your Country:
        <?php echo $this->formSelect('country', 'us', null, $this->countries) ?>
    </label></p>
    <p><label>Would you like to opt in?
        <?php echo $this->formCheckbox('opt_in', 'yes', null, array('yes', 'no')) ?>
    </label></p>
</form>
        

Результирующие выходные данные этого скрипта вида будут выглядеть наподобие этих:

<form action="action.php" method="post">
    <p><label>Your Email:
        <input type="text" name="email" value="you@example.com" size="32" />
    </label></p>
    <p><label>Your Country:
        <select name="country">
            <option value="us" selected="selected">United States</option>
            <option value="il">Israel</option>
            <option value="de">Germany</option>
        </select>
    </label></p>
    <p><label>Would you like to opt in?
        <input type="hidden" name="opt_in" value="no" />
        <input type="checkbox" name="opt_in" value="yes" checked="checked" />
    </label></p>
</form>
        

42.4.1.1. Action View Helper

The Action view helper enables view scripts to dispatch a given controller action; the result of the response object following the dispatch is then returned. These can be used when a particular action could generate re-usable content or "widget-ized" content.

Actions that result in a _forward() or redirect are considered invalid, and will return an empty string.

The API for the Action view helper follows that of most MVC components that invoke controller actions: action($action, $controller, $module = null, array $params = array()). $action and $controller are required; if no module is specified, the default module is assumed.

Пример 42.1. Basic Usage of Action View Helper

As an example, you may have a CommentController with a listAction() method you wish to invoke in order to pull a list of comments for the current request:

<div id="sidebar right"> 
    <div class="item">
        <?= $this->action('list', 'comment', null, array('count' => 10)); ?> 
    </div>
</div>

42.4.1.2. Partial Helper

The Partial view helper is used to render a specified template within its own ariable scope. The primary use is for reusable template fragments with which you do not need to worry about variable name clashes. Additionally, they allow you to specify partial view scripts from specific modules.

A sibling to the Partial, the PartialLoop view helper allows you to pass iterable data, and render a partial for each item.

Пример 42.2. Basic Usage of Partials

Basic usage of partials is to render a template fragment in its own view scope. Consider the following partial script:

<?php // partial.phtml ?>
<ul>
    <li>From: <?= $this->escape($this->from) >?</li>
    <li>Subject: <?= $this->escape($this->subject) >?</li>
</ul>

You would then call it from your view script using the following:

<?= $this->partial('partial.phtml', array(
    'from' => 'Team Framework', 
    'subject' => 'view partials')); ?>

Which would then render:

<ul>
    <li>From: Team Framework</li>
    <li>Subject: view partials</li>
</ul>

[Замечание] What is a model?

A model used with the Partial view helper can be one of the following:

  • Array. If an array is passed, it should be associative, as its key/value pairs are assigned to the view with keys as view variables.

  • Object implementing toArray() method. If an object is passed an has a toArray() method, the results of toArray() will be assigned to the view object as view variables.

  • Standard object. Any other object will assign the results of object_get_vars() (essentially all public properties of the object) to the view object.

Пример 42.3. Using PartialLoop to Render Iterable Models

Typically, you'll want to use partials in a loop, to render the same content fragment many times; this way you can put large blocks of repeated content or complex display logic into a single location. However this has a performance impact, as the partial helper needs to be invoked once for each iteration.

The PartialLoop view helper helps solve this issue. It allows you to pass an iterable item (array or object implementing Iterator) as the model. It then iterates over this, passing, the items to the partial script as the model. Items in the iterator may be any model the Partial view helper allows.

Let's assume the following partial view script:

<? // partialLoop.phtml ?>
    <dt><?= $this->key ?></dt>
    <dd><?= $this->value ?></dd>

And the following "model":

<?php
$model = array(
    array('key' => 'Mammal', 'value' => 'Camel'),
    array('key' => 'Bird', 'value' => 'Penguin'),
    array('key' => 'Reptile', 'value' => 'Asp'),
    array('key' => 'Fish', 'value' => 'Flounder'),
);
?>

In your view script, you could then invoke the PartialLoop helper:

<dl>
<?= $this->partialLoop('partialLoop.phtml', $model) ?>
</dl>
<dl></dl>
    <dt>Mammal</dt>
    <dd>Camel</dd>

    <dt>Bird</dt>
    <dd>Penguin</dd>

    <dt>Reptile</dt>
    <dd>Asp</dd>

    <dt>Fish</dt>
    <dd>Flounder</dd>

</dl>

Пример 42.4. Rendering Partials in Other Modules

Sometime a partial will exist in a different module. If you know the name of the module, you can pass it as the second argument to either partial() or partialLoop(), moving the $model argument to third position.

For instance, if there's a pager partial you wish to use that's in the 'list' module, you could grab it as follows:

<?= $this->partial('pager.phtml', 'list', $pagerData) ?>

In this way, you can re-use partials created specifically for other modules. That said, it's likely a better practice to put re-usable partials in shared view script paths.


42.4.1.3. Placeholder Helper

The Placeholder view helper is used to persist content between view scripts and view instances. It also offers some useful features such as aggregating content, capturing view script content for later use, and adding pre- and post-text to content (and custom separators for aggregated content).

Пример 42.5. Basic Usage of Placeholders

Basic usage of placeholders is to persist view data. Each invocation of the Placeholder helper expects a placeholder name; the helper then returns a placeholder container object that you can either manipulate or simply echo out.

<?php $this->placeholder('foo')->set("Some text for later") ?>

<?php 
    echo $this->placeholder('foo'); 
    // outputs "Some text for later"
?>

Пример 42.6. Using Placeholders to Aggregate Content

Aggregating content via placeholders can be useful at times as well. For instance, your view script may have a variable array from which you wish to retrieve messages to display later; a later view script can then determine how those will be rendered.

The Placeholder view helper uses containers that extend ArrayObject, providing a rich featureset for manipulating arrays. In addition, it offers a variety of methods for formatting the content stored in the container:

  • setPrefix($prefix) sets text with which to prefix the content. Use getPrefix() at any time to determine what the current setting is.

  • setPostfix($prefix) sets text with which to append the content. Use getPostfix() at any time to determine what the current setting is.

  • setSeparator($prefix) sets text with which to separate aggregated content. Use getSeparator() at any time to determine what the current setting is.

  • setIndent($prefix) can be used to set an indentation value for content. If an integer is passed, that number of spaces will be used; if a string is passed, the string will be used. Use getIndent() at any time to determine what the current setting is.

<!-- first view script -->
<?php $this->placeholder('foo')->exchangeArray($this->data) ?>
<!-- later view script -->
<?php 
$this->placeholder('foo')->setPrefix("<ul>\n    <li>")
                         ->setSeparator("</li><li>\n") 
                         ->setIndent(4)
                         ->setPostfix("</li></ul>\n");
?>

<?php 
    echo $this->placeholder('foo'); 
    // outputs as unordered list with pretty indentation
?>

Because the Placeholder container objects extend ArrayObject, you can also assign content to a specific key in the container easily, instead of simply pushing it into the container. Keys may be accessed either as object properties or as array keys.

<?php $this->placeholder('foo')->bar = $this->data ?>
<?php echo $this->placeholder('foo')->bar ?>

<?php
$foo = $this->placeholder('foo');
echo $foo['bar'];
?>

Пример 42.7. Using Placeholders to Capture Content

Occasionally you may have content for a placeholder in a view script that is easiest to template; the Placeholder view helper allows you to capture arbitrary content for later rendering using the following API.

  • captureStart($type, $key) begins capturing content.

    $type should be one of the Placeholder constants APPEND or SET. If APPEND, captured content is appended to the list of current content in the placeholder; if SET, captured content is used as the sole value of the placeholder (potentially replacing any previous content). By default, $type is APPEND.

    $key can be used to specify a specific key in the placeholder container to which you want content captured.

    captureStart() locks capturing until captureEnd() is called; you cannot nest capturing with the same placholder container. Doing so will raise an exception.

  • captureEnd() stops capturing content, and places it in the container object according to how captureStart() was called.

<!-- Default capture: append -->
<?php $this->placeholder('foo')->captureStart() 
foreach ($this->data as $datum): ?>
<div class="foo">
    <h2><?= $datum->title ?></h2>
    <p><?= $datum->content ?></p>
</div>
<?php $this->placeholder('foo')->captureEnd() ?>

<?php echo $this->placeholder('foo') ?>
<!-- Capture to key -->
<?php $this->placeholder('foo')->captureStart('SET', 'data') 
foreach ($this->data as $datum): ?>
<div class="foo">
    <h2><?= $datum->title ?></h2>
    <p><?= $datum->content ?></p>
</div>
<?php $this->placeholder('foo')->captureEnd() ?>

<?php echo $this->placeholder('foo')->data ?>

42.4.1.3.1. Concrete Placeholder Implementations

Zend Framework ships with a number of "concrete" placeholder implementations. These are for commonly used placeholders: doctype, page title, and various <head> elements. In all cases, calling the placeholder with no arguments returns the element itself.

Documentation for each element is covered separately, as linked below:

42.4.1.4. Doctype Helper

Valid HTML and XHTML documents should include a DOCTYPE declaration. Besides being difficult to remember, these can also affect how certain elements in your document should be rendered (for instance, CDATA escaping in <script> and <style> elements.

The Doctype helper allows you to specify one of the following types:

  • XHTML1_STRICT

  • XHTML1_TRANSITIONAL

  • XHTML1_FRAMESET

  • HTML4_STRICT

  • HTML4_LOOSE

  • HTML4_FRAMESET

You can also specify a custom doctype as long as it is well-formed.

The Doctype helper is a concrete implementation of the Placeholder helper.

Пример 42.8. Doctype Helper Basic Usage

You may specify the doctype at any time. However, probably the simplest use case is to specify it and output it at the same time, at the top of your layout script:

<?= $this->doctype('XHTML1_STRICT') ?>

From this point forward, any helpers that depend on the doctype for their output will be doctype aware -- and the doctype will be present in your document.


Пример 42.9. Retrieving the Doctype

If you need to know the doctype later, you can do so by calling getDoctype() on the object, which is returned by invoking the helper.

<?php
$doctype = $view->doctype()->getDoctype();
?>

Typically, you'll simply want to know if the doctype is XHTML or not; for this, the isXhtml() method will suffice:

<?php
if ($view->doctype()->isXhtml()) {
    // do something differently
}
?>

42.4.1.5. HeadLink Helper

The HTML <link> element is increasingly used for linking a variety of resources for your site: stylesheets, feeds, favicons, trackbacks, and more. The HeadTitle helper provides a simple interface for creating and aggregating these elements for later retrieval and output in your layout script.

The HeadLink helper has special methods for adding stylesheet links to its stack:

  • appendStylesheet($href, $media, $conditionalStylesheet)

  • offsetSetStylesheet($index, $href, $media, $conditionalStylesheet)

  • prependStylesheet($href, $media, $conditionalStylesheet)

  • setStylesheet($href, $media, $conditionalStylesheet)

The $media value defaults to 'screen', but may be any valid media value. $conditionalStylesheet is a boolean, and will be used at rendering time to determine if special comments should be included to prevent loading of the stylesheet on certain platforms.

Additionally, the HeadLink helper has special methods for adding 'alternate' links to its stack:

  • appendAlternate($href, $type, $title)

  • offsetSetAlternate($index, $href, $type, $title)

  • prependAlternate($href, $type, $title)

  • setAlternate($href, $type, $title)

The headLink() helper method allows specifying all attributes necessary for a <link> element, and allows you to also specify placement -- whether the new element replaces all others, prepends (top of stack), or appends (end of stack).

The HeadLink helper is a concrete implementation of the Placeholder helper.

Пример 42.10. HeadLink Helper Basic Usage

You may specify a headLink at any time. Typically, you will specify global links in your layout script, and application specific links in your application view scripts. In your layout script, in the <head> section, you will then echo the helper to output it.

<?php // setting links in a view script:
$this->headLink()->appendStylesheet('/styles/basic.css')
                 ->headLink(array('rel' => 'favicon', 'href' => '/img/favicon.ico'), 'PREPEND')
                 ->prependStylesheet('/styles/moz.css', 'screen', true);
?>
<?php // rendering the links: ?>
<?= $this->headLink() ?>

42.4.1.6. HeadMeta Helper

The HTML <meta> element is used to provide meta information about your HTML document -- typically keywords, document character set, caching pragmas, etc. Meta tags may be either of the 'http-equiv' or 'name' types, must contain a 'content' attribute, and can also have either of the 'lang' or 'scheme' modifier attributes.

The HeadMeta helper supports the following methods for setting and adding meta tags:

  • appendName($keyValue, $content, $conditionalName)

  • offsetSetName($index, $keyValue, $content, $conditionalName)

  • prependName($keyValue, $content, $conditionalName)

  • setName($keyValue, $content, $modifiers)

  • appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv)

  • offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv)

  • prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv)

  • setHttpEquiv($keyValue, $content, $modifiers)

The $keyValue item is used to define a value for the 'name' or 'http-equiv' key; $content is the value for the 'content' key, and $modifiers is an optional associative array that can contain keys for 'lang' and/or 'scheme'.

You may also set meta tags using the headMeta() helper method, which has the following signature: headMeta($content, $keyValue, $keyType = 'name', $modifiers = array(), $placement = 'APPEND'). $keyValue is the content for the key specified in $keyType, which should be either 'name' or 'http-equiv'. $placement can be either 'SET' (overwrites all previously stored values), 'APPEND' (added to end of stack), or 'PREPEND' (added to top of stack).

HeadMeta overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally modify these items by simply modifying the object returned.

The HeadMeta helper is a concrete implementation of the Placeholder helper.

Пример 42.11. HeadMeta Helper Basic Usage

You may specify a new meta tag at any time. Typically, you will specify client-side caching rules or SEO keywords.

For instance, if you wish to specify SEO keywords, you'd be creating a meta name tag with the name 'keywords' and the content the keywords you wish to associate with your page:

<?php // setting meta keywords
$this->headMeta()->appendName('keywords', 'framework php productivity');
?>

If you wishedto set some client-side caching rules, you'd set http-equiv tags with the rules you wish to enforce:

<?php // disabling client-side cache
$this->headMeta()->appendHttpEquiv('expires', 'Wed, 26 Feb 1997 08:21:57 GMT')
                 ->appendHttpEquiv('pragma', 'no-cache')
                 ->appendHttpEquiv('Cache-Control', 'no-cache');
?>

Another popular use for meta tags is setting the content type, character set, and language:

<?php // setting content type and character set
$this->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8')
                 ->appendHttpEquiv('Content-Language', 'en-US');
?>

As a final example, an easy way to display a transitional message before a redirect is using a "meta refresh":

<?php // setting a meta refresh for 3 seconds to a new url:
$this->headMeta()->appendHttpEquiv('Refresh', '3;URL=http://www.some.org/some.html');
?>

When you're ready to place your meta tags in the layout, simply echo the helper:

<?= $this->headMeta() ?>

42.4.1.7. HeadScript Helper

The HTML <script> element is used to either provide inline client-side scripting elements or link to a remote resource containing client-side scripting code. The HeadScript helper allows you to manage both.

The HeadScript helper supports the following methods for setting and adding scripts:

  • appendFile($src, $type = 'text/javascript', $attrs = array())

  • offsetSetFile($index, $src, $type = 'text/javascript', $attrs = array())

  • prependFile($src, $type = 'text/javascript', $attrs = array())

  • setFile($src, $type = 'text/javascript', $attrs = array())

  • appendScript($script, $type = 'text/javascript', $attrs = array())

  • offsetSetScript($index, $script, $type = 'text/javascript', $attrs = array())

  • prependScript($script, $type = 'text/javascript', $attrs = array())

  • setScript($script, $type = 'text/javascript', $attrs = array())

In the case of the *File() methods, $src is the remote location of the script to load; this is usually in the form of a URL or a path. For the *Script() methods, $script is the client-side scripting directives you wish to use in the element.

HeadScript also allows capturing scripts; this can be useful if you want to create the client-side script programmatically, and then place it elsewhere. The usage for this will be showed in an example below.

Finally, you can also use the headScript() method to quickly add script elements; the signature for this is headScript($mode = 'FILE', $spec, $placement = 'APPEND'). The $mode is either 'FILE' or 'SCRIPT', depending on if you're linking a script or defining one. $spec is either the script file to link or the script source itself. $placement should be either 'APPEND', 'PREPEND', or 'SET'.

HeadScript overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally modify these items by simply modifying the object returned.

The HeadScript helper is a concrete implementation of the Placeholder helper.

[Замечание] Use InlineScript for HTML Body Scripts

HeadScript's sibling helper, InlineScript, should be used when you wish to include scripts inline in the HTML body. Placing scripts at the end of your document is a good practice for speeding up delivery of your page, particularly when using 3rd party analytics scripts.

[Замечание] Arbitrary Attributes are Disabled by Default

By default, HeadScript only will render <script> attributes that are blessed by the W3C. These include 'type', 'charset', 'defer', 'language', and 'src.' However, some javascript frameworks, notably Dojo, utilize custom attributes in order to modify behavior. To allow such attributes, you can enable them via the setAllowArbitraryAttributes() method:

<?php
$this->headScript()->setAllowArbitraryAttributes(true);
?>

Пример 42.12. HeadScript Helper Basic Usage

You may specify a new script tag at any time. As noted above, these may be links to outside resource files or scripts theselves.

<?php // adding scripts
$this->headScript()->appendFile('/js/prototype.js')
                   ->appendScript($onloadScript);
?>

Order is often important with client-side scripting; you may need to ensure that libraries are loaded in a specific order due to dependencies each have; use the various append, prepend, and offsetSet directives to aid in this task:

<?php // Putting scripts in order

// place at a particular offset to ensure loaded last
$this->headScript()->offsetSetScript(100, '/js/myfuncs.js');

// use scriptaculous effects (append uses next index, 101)
$this->headScript()->appendScript('/js/scriptaculous.js');

// but always have base prototype script load first:
$this->headScript()->prependScript('/js/prototype.js');
?>

When you're finally ready to output all scripts in your layout script, simply echo the helper:

<?= $this->headScript() ?>

Пример 42.13. Capturing Scripts Using the HeadScript Helper

Sometimes you need to generate client-side scripts programmatically. While you could use string concatenation, heredocs, and the like, often it's easier just to do so by creating the script and sprinkling in PHP tags. HeadScript lets you do just that, capturing it to the stack:

<?php $this->headScript()->captureStart() ?>
var action = '<?= $this->baseUrl ?>';
$('foo_form').action = action;
<?php $this->headScript()->captureEnd() ?>

The following assumptions are made:

  • The script will be appended to the stack. If you wish for it to replace the stack or be added to the top, you will need to pass 'SET' or 'PREPEND', respectively, as the first argument to captureStart().

  • The script MIME type is assumed to be 'text/javascript'; if you wish to specify a different type, you will need to pass it as the second argument to captureStart().

  • If you wish to specify any additional attributes for the <script> tag, pass them in an array as the third argument to captureStart().


42.4.1.8. HeadStyle Helper

The HTML <style> element is used to include CSS stylesheets inline in the HTML <head> element.

[Замечание] Use HeadLink to link CSS files

HeadLink should be used to create <link> elements for including external stylesheets. HeadScript is used when you wish to define your stylesheets inline.

The HeadStyle helper supports the following methods for setting and adding stylesheet declarations:

  • appendStyle($content, $attributes = array())

  • offsetSetStyle($index, $content, $attributes = array())

  • prependStyle($content, $attributes = array())

  • setStyle($content, $attributes = array())

In all cases, $content is the actual CSS declarations. $attributes are any additional attributes you wish to provide to the style tag: lang, title, media, or dir are all permissable.

HeadStyle also allows capturing style declarations; this can be useful if you want to create the declarations programmatically, and then place them elsewhere. The usage for this will be showed in an example below.

Finally, you can also use the headStyle() method to quickly add declarations elements; the signature for this is headStyle($content$placement = 'APPEND', $attributes = array()). $placement should be either 'APPEND', 'PREPEND', or 'SET'.

HeadStyle overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally modify these items by simply modifying the object returned.

The HeadStyle helper is a concrete implementation of the Placeholder helper.

Пример 42.14. HeadStyle Helper Basic Usage

You may specify a new style tag at any time:

<?php // adding styles
$this->headStyle()->appendStyle($styles);
?>

Order is very important with CSS; you may need to ensure that declarations are loaded in a specific order due to the order of the cascade; use the various append, prepend, and offsetSet directives to aid in this task:

<?php // Putting styles in order

// place at a particular offset:
$this->headStyle()->offsetSetStyle(100, $customStyles);

// place at end:
$this->headStyle()->appendStyle($finalStyles);

// place at beginning
$this->headStyle()->prependStyle($firstStyles);
?>

When you're finally ready to output all style declarations in your layout script, simply echo the helper:

<?= $this->headStyle() ?>

Пример 42.15. Capturing Style Declarations Using the HeadStyle Helper

Sometimes you need to generate CSS style declarations programmatically. While you could use string concatenation, heredocs, and the like, often it's easier just to do so by creating the styles and sprinkling in PHP tags. HeadStyle lets you do just that, capturing it to the stack:

<?php $this->headStyle()->captureStart() ?>
body {
    background-color: <?= $this->bgColor ?>;
}
<?php $this->headStyle()->captureEnd() ?>

The following assumptions are made:

  • The style declarations will be appended to the stack. If you wish for them to replace the stack or be added to the top, you will need to pass 'SET' or 'PREPEND', respectively, as the first argument to captureStart().

  • If you wish to specify any additional attributes for the <style> tag, pass them in an array as the second argument to captureStart().


42.4.1.9. HeadTitle Helper

The HTML <title> element is used to provide a title for an HTML document. The HeadTitle helper allows you to programmatically create and store the title for later retrieval and output.

The HeadTitle helper is a concrete implementation of the Placeholder helper. It overrides the toString() method to enforce generating a <title> element, and adds a headTitle() method for quick and easy setting and aggregation of title elements. The signature for that method is headTitle($title, $setType = 'APPEND'); by default, the value is appended to the stack (aggregating title segments), but you may also specify either 'PREPEND' (place at top of stack) or 'SET' (overwrite stack).

Пример 42.16. HeadTitle Helper Basic Usage

You may specify a title tag at any time. A typical usage would have you setting title segments for each level of depth in your application: site, controller, action, and potentially resource.

<?php 
// setting the controller and action name as title segments:
$request = Zend_Controller_Front::getInstance()->getRequest();
$this->headTitle($request->getActionName())
     ->headTitle($request->getControllerName());

// setting the site in the title; possibly in the layout script:
$this->headTitle('Zend Framework');

// setting a separator string for segments:
$this->headTitle()->setSeparator(' / ');
?>

When you're finally ready to render the title in your layout script, simply echo the helper:

<!-- renders <action> / <controller> / Zend Framework -->
<?= $this->headTitle() ?>

42.4.1.10. InlineScript Helper

The HTML <script> element is used to either provide inline client-side scripting elements or link to a remote resource containing client-side scripting code. The InlineScript helper allows you to manage both. It is derived from HeadScript, and any method of that helper is available; however, use the inlineScript() method in place of headScript().

[Замечание] Use InlineScript for HTML Body Scripts

InlineScript, should be used when you wish to include scripts inline in the HTML body. Placing scripts at the end of your document is a good practice for speeding up delivery of your page, particularly when using 3rd party analytics scripts.

Some JS libraries need to be included in the HTML head; use HeadScript for those scripts.

42.4.1.11. JSON Helper

When creating views that return JSON, it's important to also set the appropriate response header. The JSON view helper does exactly that. In addition, by default, it disables layouts (if currently enabled), as layouts generally aren't used with JSON responses.

The JSON helper sets the following header:

Content-Type: application/json

Most AJAX libraries look for this header when parsing responses to determine how to handle the content.

Usage of the JSON helper is very straightforward:

<?php
<?= $this->json($this->data) ?>
?>

42.4.1.12. Translate Helper

Often web sites are available in several languages. To translate the content of a site you should simply use Zend Translate and to integrate Zend Translate within your view you should use the Translate View Helper.

In all following examples we are using the simple Array Translation Adapter. Of course you can also use any instance of Zend_Translate and also any subclasses of Zend_Translate_Adapter. There are several ways to initiate the Translate View Helper:

  • Registered, through a previously registered instance in Zend_Registry

  • Afterwards, through the fluent interface

  • Directly, through initiating the class

A registered instance of Zend_Translate is the preferred usage for this helper. You can also select the locale to be used simply before you add the adapter to the registry.

[Замечание] Замечание

We are speaking of locales instead of languages because a language also may contain a region. For example English is spoken in different dialects. There may be a translation for British and one for American English. Therefore, we say "locale" instead of "language."

Пример 42.17. Registered instance

To use a registered instance just create an instance of Zend_Translate or Zend_Translate_Adapter and register it within Zend_Registry using Zend_Translate as its key.

<?php
// our example adapter
$adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de');
Zend_Registry::set('Zend_Translate', $adapter);

// within your view
echo $this->translate('simple');
// this returns 'einfach'
?>

If you are more familiar with the fluent interface, then you can also create an instace within your view and initiate the helper afterwards.

Пример 42.18. Within the view

To use the fluent interface, create an instance of Zend_Translate or Zend_Translate_Adapter, call the helper without a parameter, and call the setTranslator() method.

<?php
// within your view
$adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de');
$this->translate()->setTranslator($adapter)->translate('simple');
// this returns 'einfach'
?>

If you are using the helper without Zend_View then you can also use it directly.

Пример 42.19. Direct usage

<?php
// our example adapter
$adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de');

// initiate the adapter
$translate = new Zend_View_Helper_Translate($adapter);
print $translate->translate('simple'); // this returns 'einfach'
?>

You would use this way if you are not working with Zend_View and need to create translated output.


As already seen, the translate() method is used to return the translation. Just call it with the needed messageid of your translation adapter. But it can also replace parameters within the translation string. Therefore, it accepts variable parameters in two ways: either as a list of parameters, or as an array of parameters. As examples:

Пример 42.20. Single parameter

To use a single parameter just add it to the method.

<?php
// within your view
$date = "Monday";
$this->translate('Today is %1\$s', $date);
// could return 'Heute ist Monday'
?>

[Замечание] Замечание

Keep in mind that if you are using parameters which are also text, you may also need to translate these parameters.

Пример 42.21. List of parameters

Or use a list of parameters and add it to the method.

<?php
// within your view
$date = "Monday";
$month = "April";
$time = "11:20:55";
$this->translate('Today is %1\$s in %2\$s. Actual time: %3\$s', $date, $month, $time);
// Could return 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55'
?>

Пример 42.22. Array of parameters

Or use an array of parameters and add it to the method.

<?php
// within your view
$date = array("Monday", "April", "11:20:55");
$this->translate('Today is %1\$s in %2\$s. Actual time: %3\$s', $date);
// Could return 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55'
?>

Sometimes it is necessary to change the locale of the translation. This can be done either dynamically per translation or statically for all following translations. And you can use it with both a parameter list and an array of parameters. In both cases the locale must be given as the last single parameter.

Пример 42.23. Change locale dynamically

<?php
// within your view
$date = array("Monday", "April", "11:20:55");
$this->translate('Today is %1\$s in %2\$s. Actual time: %3\$s', $date, 'it');
?>

This example returns the Italian translation for the messageid. But it will only be used once. The next translation will use the locale from the adapter. Normally you will set the desired locale within the translation adapter before you add it to the registry. But you can also set the locale from within the helper:

Пример 42.24. Change locale statically

<?php
// within your view
$date = array("Monday", "April", "11:20:55");
$this->setLocale('it')->translate('Today is %1\$s in %2\$s. Actual time: %3\$s', $date);
?>

The above example sets 'it' as the new default locale which will be used for all further translations.

Of course there is also a getLocale() method to get the currently set locale.

Пример 42.25. Get the currently set locale

<?php
// within your view
$date = array("Monday", "April", "11:20:55");

// returns 'de' as set default locale from our above examples
$this->getLocale();

$this->setLocale('it')->translate('Today is %1\$s in %2\$s. Actual time: %3\$s', $date);

// returns 'it' as new set default locale
$this->getLocale();
?>

42.4.2. Пути к классам помощников

Как и для скриптов вида, ваш контроллер может задать стек путей, в которых Zend_View должен искать классы помощников. По умолчанию Zend_View ищет классы помощников в Zend/View/Helper/*. Используя методы setHelperPath() и addHelperPath(), вы можете укзать Zend_View, чтобы он искал классы помощников в других местах. Кроме этого, вы можете указать префикс класса, используемый для помощников, находящихся в данном пути; префикс обеспечивает пространство имен. Если префикс не указан, то по умолчанию используется 'Zend_View_Helper_'.

<?php
$view = new Zend_View();

// Устанавливает путь /path/to/more/helpers с префиксом 'My_View_Helper'
$view->setHelperPath('/path/to/more/helpers', 'My_View_Helper');
        

Фактически вы можете "складывать" в стек пути, используя метод addHelperPath(). Если вы добавили пути в стек, то Zend_View будет искать запрошенный класс помощника в этих путях, начиная с пути, добавленного последним. Это дает возможность добавлять к начальному набору своих помощников (или даже замещать имеющиеся).

<?php
$view = new Zend_View();
// Добавить /path/to/some/helpers с префиксом для классов 'My_View_Helper'
$view->addHelperPath('/path/to/some/helpers', 'My_View_Helper);
// Добавить /other/path/to/helpers с префиксом для классов 'Your_View_Helper'
$view->addHelperPath('/other/path/to/helpers', 'Your_View_Helper');

// теперь, когда вы вызываете $this->helperName(), Zend_View будет искать
// "/other/path/to/helpers/HelperName.php" с классом "My_View_Helper_HelperName",
// затем "/path/to/some/helpers/HelperName" с классом "Your_View_Helper_HelperName",
// и под конец "Zend/View/Helper/HelperName.php" с классом "Zend_View_Helper_HelperName".
        

42.4.3. Написание собственных помощников

Написать собственного помощника довольно просто — просто следуйте этим правилам:

  • Имя класса должно, как минимум, заканчиваться именем помощника в формате CamelCaps. Т.е. если вы пишете помощника с именем "specialPurpose", то минимальное имя класса должно быть "SpecialPurpose". Вы можете (и должны) давать классам имена с префиксом, рекомендуется использовать 'View_Helper' как часть этого префикса: "My_View_Helper_SpecialPurpose" (Вам нужно будет передать этот префикс с или без завершающего знака подчеркивания методу addHelperPath() или setHelperPath()).

  • Класс должен иметь открытый метод, имя которого соответствует имени помощника. Это метод, который будет вызываться, когда ваш шаблон выполняет вызов $this->specialPurpose(). В нашем примере с помощником "specialPurpose" объявление требуемого метода должно быть public function specialPurpose().

  • Обычно класс не должен выполнять вывод, вместо этого он должен возвращать значение для вывода. Возвращаемое значение должно быть экранировано должным образом.

  • Класс должен быть в файле, названном по имени класса. Снова используя пример с помощником "specialPurpose", мы должны дать файлу имя "SpecialPurpose.php".

Размещайте класс помощника где-либо в одном из находящихся в стеке путей к помощникам, и Zend_View будет автоматически загружать, инстанцировать, сохранять и выполнять его.

Вот пример кода нашего помощника "SpecialPurpose":

<?php class My_View_Helper_SpecialPurpose {
    protected $_count = 0;
    public function specialPurpose()
    {
        $this->_count++;
        $output = "I have seen 'The Jerk' {$this->_count} time(s).";
        return htmlspecialchars($output);
    }
}
}
        

Далее в скрипте вида вы можете вызывать помощника SpecialPurpose сколько угодно раз. Он будет инстанцирован один раз, и сохраняется в течение существования экземпляра Zend_View.

<?php
// помните, что в скрипте вида $this ссылается на экземпляр Zend_View
echo $this->specialPurpose();
echo $this->specialPurpose();
echo $this->specialPurpose();
        

Результат должен выглядеть наподобие следующего:

I have seen 'The Jerk' 1 time(s).
I have seen 'The Jerk' 2 time(s).
I have seen 'The Jerk' 3 time(s).
        

Иногда бывает, что нужен доступ к объекту Zend_View - например, нужно получить зарегистрированное значение кодировки или произвести рендеринг другого скрипта вида как часть действий, выполняемых вашим помощником. Для того, чтобы можно было получить доступ к объекту вида, ваш класс помощника должен иметь метод setView($view), пример которого показан ниже:

<?php class My_View_Helper_ScriptPath
{
    public $view;

    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }

    public function scriptPath($script)
    {
        return $this->view->getScriptPath($script);
    }
}
        

Если ваш класс помощника имеет метод setView(), то он будет вызываться при первом инстанцировании класса помощника и его передаче текущему объекту вида. На ваше усмотрение остается то, как в вашем классе помощника должен сохраняться объект вида и производиться доступ к нему.

    Поддержать сайт на родительском проекте КГБ