This package provides a proxy generator for Symfony's dependency injection component that generates super tiny, super simple proxies, especially when compared to Symphony's default implementation.
If you're not familiar with proxy services, better have a look at Symfony's documentation before going any further.
The generator works with the following assumptions: the service we want to proxy implements an interface and services
using that service expect that interface too. Pretty normal stuff. Consider the following code, where an
ExceptionHandler
service requires a logger implementing LogInterface
:
<?php
use Psr\Log\LoggerInterface;
class ExceptionHandler
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
// …
}
Now imagine we're using Monolog as a logger, and we have an expansive stream to setup. Why waste time building that logger for every request when it's seldom used? That's when we mark our service as lazy.
The following example demonstrates how we can mark our Psr\Log\LoggerInterface
service as lazy (we could use PHP code
or XML just the same):
services:
Psr\Log\LoggerInterface:
class: Monolog\Logger
lazy: true
# …
The service can also use a factory:
services:
Psr\Log\LoggerInterface:
factory: 'LoggerFactory::build'
lazy: true
# …
We don't have to define our service with a class, we could use
logger
instead ofPsr\Log\LoggerInterface
just the same, except we would have to defineclass
for the factory one.
Now let's see how to build our container.
The following code demonstrates how to build, compile, and dump a container:
<?php
use olvlvl\SymfonyDependencyInjectionProxy\FactoryRenderer;
use olvlvl\SymfonyDependencyInjectionProxy\InterfaceResolver\BasicInterfaceResolver;
use olvlvl\SymfonyDependencyInjectionProxy\MethodRenderer;
use olvlvl\SymfonyDependencyInjectionProxy\ProxyDumper;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
$builder = new ContainerBuilder();
// …
// Here we load our config, or build the container using clever PHP calls.
// We might event have some compile passes to add.
// …
$builder->compile();
$dumper = new PhpDumper($builder);
$dumper->setProxyDumper(new ProxyDumper(
new BasicInterfaceResolver(),
new FactoryRenderer(new MethodRenderer)
));
/* @var string $containerFile */
file_put_contents($containerFile, $dumper->dump());
There you have it. We can use our container as usual and everything is awesome and cute.
The basic interface resolver will have a hard time figuring out which interface to implement if a service implements
many. For instance, if a service was an instance of ArrayObject
the following exception would be raised:
Don't know which interface to choose from for ArrayObject: IteratorAggregate, Traversable, ArrayAccess, Serializable, Countable.
We can specify which interface to implement using the proxy
tag:
ArrayObject:
lazy: true
tags:
- { name: proxy, interface: ArrayAccess }
And since symfony/dependency-injection
v4.2 we can specify the interface to implement using the lazy
attribute:
ArrayObject:
lazy: ArrayAccess
The package requires PHP 7.1 or later.
The recommended way to install this package is through Composer:
$ composer require olvlvl/symfony-dependency-injection-proxy
The package is available on GitHub, its repository can be cloned with the following command line:
$ git clone https://github.com/olvlvl/symfony-dependency-injection-proxy.git
The test suite is ran with the make test
command. PHPUnit and
Composer need to be globally available to run the suite. The command
installs dependencies as required. The make test-coverage
command runs test suite and also creates
an HTML coverage report in build/coverage
. If your environment doesn't meet the requirements you can run the tests
with a container, run make test-container
to create it.
The package is continuously tested by Travis CI.
olvlvl/symfony-dependency-injection-proxy is licensed under the New BSD License - See the LICENSE file for details.