Skip to content

Instantly share code, notes, and snippets.

@Punk-UnDeaD
Created December 20, 2020 20:03
Show Gist options
  • Save Punk-UnDeaD/8882e74c5dd2ba66d1dc9ca038cd2800 to your computer and use it in GitHub Desktop.
Save Punk-UnDeaD/8882e74c5dd2ba66d1dc9ca038cd2800 to your computer and use it in GitHub Desktop.
AutoInject
<?php
declare(strict_types=1);
namespace App\Container;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class AutoInject
{
}
<?php
declare(strict_types=1);
namespace App\Container;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class AutoInjectorCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
foreach ($container->getDefinitions() as $name => $definition) {
$class = $definition->getClass() ?? $name;
if (in_array($class, get_declared_classes())
&& is_subclass_of($class, AutoInjectorInterface::class)
) {
$reflection = new \ReflectionClass($class);
$properties = $reflection->getProperties();
foreach ($properties as $property) {
if ($attributes = $property->getAttributes(AutoInject::class)) {
$definition->addMethodCall(
'inject',
[$property->getName(), new Reference($property->getType()->getName())]
);
}
}
}
}
}
}
<?php
declare(strict_types=1);
namespace App\Container;
interface AutoInjectorInterface
{
public function inject(string $field, $service);
}
<?php
declare(strict_types=1);
namespace App\Container;
trait AutoInjectorTrait
{
public function inject(string $field, $service)
{
$this->$field = $service;
}
}
@Punk-UnDeaD
Copy link
Author

при компиляции контейнера, если класс реализует интерфейс, то если у свойства есть аттрибут, в определение сервиса добавляется вызов с именем свойства и подходящим сервисом из контейнера

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment