On this page
Lazy Services
Laminas\ServiceManager
can use 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 you to delay that overhead until the object is really needed.
Setup
Laminas\ServiceManager\Proxy\LazyServiceFactory
is a delegator factory
capable of generating lazy loading proxies for your services.
The lazy service facilities depend on ProxyManager; you will need to install that package before using the feature:
$ composer require friendsofphp/proxy-manager-lts
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:
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:
use MyApp\Buzzer;
use Laminas\ServiceManager\Factory\InvokableFactory;
use Laminas\ServiceManager\Proxy\LazyServiceFactory;
use Laminas\ServiceManager\ServiceManager;
$serviceManager = new \Laminas\ServiceManager\ServiceManager([
'factories' => [
Buzzer::class => InvokableFactory::class,
],
'lazy_services' => [
// Mapping services to their class names is required
// since the ServiceManager is not a declarative DIC.
'class_map' => [
Buzzer::class => Buzzer::class,
],
],
'delegators' => [
Buzzer::class => [
LazyServiceFactory::class,
],
],
]);
This configuration tells the service manager to add the add
LazyServiceFactory
as a delegator for Buzzer
.
You can now retrieve the buzzer:
use MyApp\Buzzer;
$buzzer = $serviceManager->get(Buzzer::class);
echo $buzzer->buzz();
To verify that the proxying occurred correctly, you can run the following code,
which should delay the 5 seconds wait time hardcoded in Buzzer::__construct
until Buzzer::buzz
is invoked:
use MyApp\Buzzer;
for ($i = 0; $i < 100; $i += 1) {
$buzzer = $serviceManager->get(Buzzer::class);
echo "created buzzer $i\n";
}
echo $buzzer->buzz();
Configuration
This is the config structure expected by Laminas\ServiceManager\Proxy\LazyServiceFactory
,
in the lazy_services
key passed in the service manager configuration:
[
// map of service names and their relative class names - this
// is required since the service manager cannot know the
// class name of defined services up front
'class_map' => [
// '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,
];
After you have an instance, you can map lazy service/class pairs using
mapLazyService()
:
$container->mapLazyService('foo', \MyApplication\Foo::class);