interitty / di
Provides some additional features into the great Nette\DI container.
Requires
- php: ~8.3
- dg/composer-cleaner: ~2.2
- nette/di: ~3.2, !=3.2.2
Requires (Dev)
- interitty/code-checker: ~1.0
- interitty/phpunit: ~1.0
- nette/application: ~3.2
- nette/bootstrap: ~3.2
- nette/caching: ~3.3
README
Provides some additional features into the great Nette\DI container.
Requirements
- PHP >= 8.3
Installation
The best way to install interitty/di is using Composer:
composer require interitty/di
Features
The abstract CompilerExtension
class provides the standard way to work with the default parameters, expand them and validate them.
It also contains the setupServiceAlias
helper that simplifies the process of registering service or the alias when the service was registered before.
Literal factory
For generating more complicated entries, the Nette\PhpGenerator\Literal
class can be used. The createLiteral
helper factory is available for easier work.
Example: createLiteral
<?php
declare(strict_types=1);
namespace Interitty\Foo\Nette\DI;
use Interitty\DI\CompilerExtension;
use Nette\DI\Definitions\ServiceDefinition;
class FooExtension extends CompilerExtension
{
/**
* Foo helper
*
* @param ServiceDefinition $definition
* @return void
*/
protected function processFoo(ServiceDefinition $definition): void
{
$definition->addSetup('?', [$this->createLiteral('return ?;', [true])]);
}
}
Registration helpers
Sometimes it can be useful to be able to register an extension directly in a specific order before or after another extension. For this purpose,
there are auxiliary methods processRegisterAfter
and processRegisterBefore
that can be called in the constructor or initialization phase
of a process to move the extension to the exact location.
<?php
declare(strict_types=1);
namespace Interitty\Foo\Nette\DI;
use Interitty\DI\CompilerExtension;
class FooExtension extends CompilerExtension
{
/**
* @inheritdoc
*/
public function loadConfiguration(): void
{
parent::loadConfiguration();
$this->processRegisterAfter('services');
}
}
Suggestions
It also consists of the following suggestions:
- Every config parameter should be defined as the
CONFIG_*
constant with his name. - Every config parameter should be validated in the
configSchema
orprocessConfig
method. - Every service name should be defined as the
PROVIDER_*
constant. - Every service should be registered in the
setup*
method. - Setup methods should be called in the
beforeCompile
method.
Example: FooExtension
<?php
declare(strict_types=1);
namespace Interitty\Foo\Nette\DI;
use Interitty\Utils\Validators;
use Interitty\DI\CompilerExtension;
use function assert;
class FooExtension extends CompilerExtension
{
/** All config parameter name constants */
const string CONFIG_FOO = 'foo';
/** All available provider name constants */
const string PROVIDER_BAR = 'bar';
/**
* @var mixed[]
*/
protected $defaults = [
self::CONFIG_FOO => 'foo',
];
/**
* @inheritdoc
*/
public function beforeCompile(): void
{
$this->setupFoo();
}
/**
* @inheritdoc
*/
public function processConfig(): array
{
$config = parent::processConfig();
assert(Validators::check($config[self::CONFIG_FOO], 'string', self::CONFIG_FOO));
return $config;
}
// <editor-fold defaultstate="collapsed" desc="Helpers">
/**
* Bar setup helper
*
* @return void
*/
protected function setupBar(): void
{
if ($this->setupServiceAlias(Bar::class, self::PROVIDER_BAR) === false) {
$builder = $this->getContainerBuilder();
$builder->addDefinition($this->prefix(self::PROVIDER_BAR))
->setImplement(Bar::class)
->addSetup('setFoo', [$this->getConfigField(self::CONFIG_FOO));
}
}
}