Package Home

Zend Framework 2 Documentation (Manual)

PHK Home

File: /_sources/modules/zend.view.helpers.advanced-usage.txt

Size:6625
Storage flags:no_autoload,compress/gzip (32%)

.. _zend.view.helpers.advanced-usage:

Advanced usage of helpers
=========================

.. _zend.view.helpers.register:

Registering Helpers
-------------------

``Zend\View\Renderer\PhpRenderer`` composes a *plugin manager* for managing helpers, specifically an instance of
``Zend\View\HelperPluginManager``, which extends ``Zend\ServiceManager\AbstractPluginManager``, and this extends
``Zend\ServiceManager\ServiceManager``. As you can see, the *HelperPluginManager* is a specialized service manager,
so you can register a helper/plugin like any other service (see :ref:`the Service Manager documentation
<zend.service-manager.intro>` for more information).

Programmatically, this is done as follows:

.. code-block:: php
   :linenos:

   // $view is an instance of PhpRenderer
   $pluginManager = $view->getHelperPluginManager();

   // Register as a invokable class:
   $pluginManager->setInvokableClass('lowercase', 'MyModule\View\Helper\LowerCase');

   // Register as a factory:
   $pluginManager->setFactory('lowercase', function ($pluginManager) {
      $lowercaseHelper = new MyModule\View\Helper\LowerCase;

      // ...do some configuration or dependency injection...

      return $lowercaseHelper;
   });

Within an MVC application, you will typically simply pass a map of plugins to the class via your configuration.

.. code-block:: php
   :linenos:

   // From within a configuration file
   return array(
      'view_helpers' => array(
         'invokables' => array(
            'lowercase' => 'MyModule\View\Helper\LowerCase',
            'uppercase' => 'MyModule\View\Helper\UpperCase',
         ),
      ),
   );

If your module class implements ``Zend\ModuleManager\Feature\ViewHelperProviderInterface``, or just the method
``getViewHelperConfig()``, you could do the following (it's the same as the previous example).

.. code-block:: php
   :linenos:

   namespace MyModule;

   class Module
   {
       public function getAutoloaderConfig(){ /*common code*/ }
       public function getConfig(){ /*common code*/ }

       public function getViewHelperConfig()
       {
           return array(
              'invokables' => array(
                 'lowercase' => 'MyModule\View\Helper\LowerCase',
                 'uppercase' => 'MyModule\View\Helper\UpperCase',
              ),
           );
      }
   }

The two latter examples can be done in each module that needs to register helpers with the ``PhpRenderer``;
however, be aware that another module can register helpers with the same name, so order of modules can impact
which helper class will actually be registered!

.. _zend.view.helpers.custom:

Writing Custom Helpers
----------------------

Writing custom helpers is easy. We recommend extending ``Zend\View\Helper\AbstractHelper``, but at the minimum, you
need only implement the ``Zend\View\Helper\HelperInterface`` interface:

.. code-block:: php
   :linenos:

   namespace Zend\View\Helper;

   use Zend\View\Renderer\RendererInterface as Renderer;

   interface HelperInterface
   {
       /**
        * Set the View object
        *
        * @param  Renderer $view
        * @return HelperInterface
        */
       public function setView(Renderer $view);

       /**
        * Get the View object
        *
        * @return Renderer
        */
       public function getView();
   }

If you want your helper to be capable of being invoked as if it were a method call of the ``PhpRenderer``, you
should also implement an ``__invoke()`` method within your helper.

As previously noted, we recommend extending ``Zend\View\Helper\AbstractHelper``, as it implements the methods
defined in ``HelperInterface``, giving you a headstart in your development.

Once you have defined your helper class, make sure you can autoload it, and then :ref:`register it with the plugin
manager <zend.view.helpers.register>`.

Here is an example helper, which we're titling "SpecialPurpose"

.. code-block:: php
   :linenos:

   // /module/src/MyModule/View/Helper/SpecialPurpose.php
   namespace MyModule\View\Helper;

   use Zend\View\Helper\AbstractHelper;

   class SpecialPurpose extends AbstractHelper
   {
       protected $count = 0;

       public function __invoke()
       {
           $this->count++;
           $output = sprintf("I have seen 'The Jerk' %d time(s).", $this->count);
           return htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
       }
   }

Then assume that we :ref:`register it with the plugin manager <zend.view.helpers.register>`, by the name
"specialpurpose".

Within a view script, you can call the ``SpecialPurpose`` helper as many times as you like; it will be instantiated
once, and then it persists for the life of that ``PhpRenderer`` instance.

.. code-block:: php
   :linenos:

   // remember, in a view script, $this refers to the Zend\View\Renderer\PhpRenderer instance.
   echo $this->specialPurpose();
   echo $this->specialPurpose();
   echo $this->specialPurpose();

The output would look something like this:

.. code-block:: php
   :linenos:

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

Sometimes you will need access to the calling ``PhpRenderer`` object -- for instance, if you need to use the
registered encoding, or want to render another view script as part of your helper. This is why we define the
``setView()`` and ``getView()`` methods. As an example, we could rewrite the ``SpecialPurpose`` helper as follows
to take advantage of the ``EscapeHtml`` helper:

.. code-block:: php
   :linenos:

   namespace MyModule\View\Helper;

   use Zend\View\Helper\AbstractHelper;

   class SpecialPurpose extends AbstractHelper
   {
       protected $count = 0;

       public function __invoke()
       {
           $this->count++;
           $output  = sprintf("I have seen 'The Jerk' %d time(s).", $this->count);
           $escaper = $this->getView()->plugin('escapehtml');
           return $escaper($output);
       }
   }

.. _zend.view.helpers.registering-concrete:

Registering Concrete Helpers
----------------------------

Sometimes it is convenient to instantiate a view helper, and then register it with the renderer. This can be done
by injecting it directly into the plugin manager.

.. code-block:: php
   :linenos:

   // $view is a PhpRenderer instance

   $helper = new MyModule\View\Helper\LowerCase;
   // ...do some configuration or dependency injection...

   $view->getHelperPluginManager()->setService('lowercase', $helper);

The plugin manager will validate the helper/plugin, and if the validation passes, the helper/plugin will be
registered.

For more information about the PHK package format: http://phk.tekwire.net