|
 |
Zend Framework 2 Documentation (Manual) |  |
|
File: /_sources/modules/zend.service-manager.lazy-services.txt
Size: | 5200 |
Storage flags: | no_autoload,compress/gzip (35%) |
.. _zend.service-manager.lazy-services:
Lazy Services
=============
``Zend\ServiceManager`` can use :ref:`delegator factories <zend.service-manager.delegator-factories>` to
generate "lazy" references to your services.
Lazy services are `proxies`_ that get lazily instantiated, and keep a reference to the real instance of
the proxied service.
Use cases
^^^^^^^^^
You may want to lazily initialize a service when it is instantiated very often, but not always used.
A typical example is a database connection: it is a dependency to many other elements in your application,
but that doesn't mean that every request will execute queries through it.
Additionally, instantiating a connection to the database may require some time and eat up resources.
Proxying the database connection would allow to delay that overhead until the object is really needed.
Setup
^^^^^
``Zend\ServiceManager\Proxy\LazyServiceFactory`` is a :ref:`delegator factory <zend.service-manager.delegator-factories>` capable of generating
lazy loading proxies for your services.
The ``LazyServiceFactory`` depends on `ProxyManager`_, so be sure to install it before going through
the following steps:
.. code-block:: sh
:linenos:
php composer.phar require ocramius/proxy-manager:0.3.*
Practical example
^^^^^^^^^^^^^^^^^
To demonstrate how a lazy service works, you may use the following ``Buzzer`` example class, which
is designed to be slow at instantiation time for demonstration purposes:
.. code-block:: php
:linenos:
namespace MyApp;
class Buzzer
{
public function __construct()
{
// deliberately halting the application for 5 seconds
sleep(5);
}
public function buzz()
{
return 'Buzz!';
}
}
You can then proceed and configure the service manager to generate proxies instead of real services:
.. code-block:: php
:linenos:
$serviceManager = new \Zend\ServiceManager\ServiceManager();
$config = array(
'lazy_services' => array(
// mapping services to their class names is required
// since the ServiceManager is not a declarative DIC
'class_map' => array(
'buzzer' => 'MyApp\Buzzer',
),
),
);
$serviceManager->setService('Config', $config);
$serviceManager->setInvokableClass('buzzer', 'MyApp\Buzzer');
$serviceManager->setFactory('LazyServiceFactory', 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory');
$serviceManager->addDelegator('buzzer', 'LazyServiceFactory');
This will tell the service manager to use the ``LazyServiceFactory`` delegator factory to
instantiate the ``buzzer`` service.
As you may have noticed, the standard setup for the ``LazyServiceFactory`` requires you to define
a ``Config`` service. That's because the functionality was thought to be easily integrated into
``Zend\Mvc``.
You can now simply retrieve the ``buzzer``:
.. code-block:: php
:linenos:
$buzzer = $serviceManager->get('buzzer');
echo $buzzer->buzz();
To verify that the proxying occurred correctly, you can simply run the following code, which should delay
the 5 seconds wait time hardcoded in ``Buzzer::__construct`` until ``Buzzer::buzz`` is invoked:
.. code-block:: php
:linenos:
for ($i = 0; $i < 100; $i += 1) {
$buzzer = $serviceManager->create('buzzer');
echo "created buzzer $i\n";
}
echo $buzzer->buzz();
The setup above can also be represented via configuration in an MVC application's context:
.. code-block:: php
:linenos:
return array(
'service_manager' => array(
'invokables' => array(
'buzzer' => 'MyApp\Buzzer',
),
'delegators' => array(
'buzzer' => array(
'LazyServiceFactory'
),
),
'factories' => array(
'LazyServiceFactory' => 'Zend\ServiceManager\Proxy\LazyServiceFactoryFactory',
),
),
'lazy_services' => array(
'class_map' => array(
'buzzer' => 'MyApp\Buzzer',
),
),
);
Configuration
^^^^^^^^^^^^^
This is the config structure expected by ``Zend\ServiceManager\Proxy\LazyServiceFactoryFactory``:
.. code-block:: php
:linenos:
return array(
'lazy_services' => array(
// map of service names and their relative class names - this
// is required since the service manager cannot know the
// class name of defined services upfront
'class_map' => array(
// 'foo' => 'MyApplication\Foo',
),
// directory where proxy classes will be written - default to system_get_tmp_dir()
'proxies_target_dir' => null,
// namespace of the generated proxies, default to "ProxyManagerGeneratedProxy"
'proxies_namespace' => null,
// whether the generated proxy classes should be written to disk or generated on-the-fly
'write_proxy_files' => false,
),
);
.. _`proxies`: http://en.wikipedia.org/wiki/Proxy_pattern
.. _`ProxyManager`: https://github.com/Ocramius/ProxyManager
For more information about the PHK package format: http://phk.tekwire.net