highcore/registry-bundle

Symfony 注册表包,包含 highcore/registry 包的所有编译器遍历。

v2.0.10 2024-09-02 21:11 UTC

This package is auto-updated.

Last update: 2024-09-17 15:46:18 UTC


README

RegistryBundle 是一个提供便捷机制以处理注册表的 Symfony 包。此包允许您自动在注册表中注册具有特定属性和接口的服务。

安装

要安装此包,请使用 Composer

composer require highcore/registry-bundle

配置

安装后,将 RegistryBundle 添加到您的 Symfony 配置文件(config/bundles.php)中

return [
    // ...
    Highcore\Bundle\RegistryBundle\RegistryBundle::class => ['all' => true],
];

使用

注册注册表

注册表通过编译器遍历在包类中注册。这允许标记了属性的服务在容器编译阶段自动注册到适当的注册表中。

注册注册表的示例

<?php
declare(strict_types=1)

namespace App\YourBundle;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Highcore\Bundle\RegistryBundle\Compiler\Pass\ServiceAttributeRegistryPass;
use Highcore\Component\Criteria\Doctrine\Handler\CriteriaRepository;
use Highcore\Bundle\RegistryBundle\Registry\IdentityServiceRegistry;
use Highcore\Bundle\RegistryBundle\Registry\ServiceRegistry;

class YourBundle extends Bundle
{
    public function build(ContainerBuilder $container): void
    {
        parent::build($container);

        $container->addCompilerPass(new ServiceAttributeRegistryPass(
            definitionId: 'some.your.project.namespace.first.resource.registry',
            definitionClass: IdentityServiceRegistry::class,
            targetClassAttribute: \App\YourBundle\Attribute\AsYourResourceAttribute::class, // your attribute class
            interface: \App\YourBundle\YourServiceInterface::class, // your interface class (interface is optional, if passed, CompilerPass will check your service for an implementation of that interface)
        ));

        $container->addCompilerPass(new ServiceAttributeRegistryPass(
            definitionId: 'some.your.project.namespace.second.resource.registry',
            definitionClass: ServiceRegistry::class,
            targetClassAttribute: \App\YourBundle\Attribute\AsYourSecondResourceAttribute::class,
            // register registry without interface
        ));
    }
}

在此示例中,使用编译器遍历注册了两个注册表

第一个资源的注册表

注册所有标记了 \App\AsYourResourceAttribute 属性的服务,并且每个服务都必须实现 \App\YourServiceInterface 接口。

  1. 第一个注册表的示例接口
<?php
declare(strict_types=1)

namespace App\YourBundle;

interface YourServiceInterface
{
    public function yourMethod(): void;
}
  1. 第一个注册表的示例属性
<?php
declare(strict_types=1)

namespace App\YourBundle\Attribute;

use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;

#[\Attribute(\Attribute::TARGET_CLASS)]
#[NamedArgumentConstructor]
class AsYourResourceAttribute implements IdentityServiceAttributeInterface
{
    public function __construct(private readonly ?string $identifier = null)
    {
    }

    // If self::hasIdentifier() returns false, this method will not be called,
    // instead we will take the name of the class to which this attribute will be assigned as the identifier
    public function getIdentifier(): string
    {
        return $this->identifier;
    }

    public function hasIdentifier(): bool
    {
        return null !== $this->identifier;
    }
}

第二个资源的注册表

注册所有标记了 \App\AsYourSecondResourceAttribute 属性的服务。

例如,对于第二个注册表,我们只会创建属性

<?php
declare(strict_types=1)

namespace App;

use Highcore\Component\Registry\Attribute\ServiceAttributeInterface;

#[\Attribute(\Attribute::TARGET_CLASS)]
class AsYourSecondResourceAttribute implements ServiceAttributeInterface
{
}

在注册表中注册服务

可以通过属性自动将服务添加到注册表中。只需将属性添加到要注册的服务类中,并在 symfony 服务容器中注册它们即可

<?php
declare(strict_types=1);

namespace App\YourBundle\Service;

use Highcore\JsonApi\Configurator\JsonApiResourceConfigurator;
use App\YourBundle\Attribute\AsYourResourceAttribute;
use App\YourBundle\YourServiceInterface;

#[AsYourResourceAttribute('some_identifier')]
class MyService implements YourServiceInterface
{
    public function yourMethod(): void
    {
        // Implementation of the configurator
    }
}

在 symfony 容器中注册您的服务

# src/YourBundle/Resources/config/services.php
<?php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $configurator): void {
    $services = $configurator->services();
    $defaults = $services->defaults();
    $defaults->autowire();
    $defaults->autoconfigure();

    // that's all you need to register your service in the registry
    $services->set(\App\YourBundle\Service\MyService::class);
};

使用注册表

要开始,注册您的服务并将注册表 "some.your.project.namespace.first.resource.registry" 作为参数传递。从之前在 \App\YourBundle::build() 中使用的 definitionId 中获取 ServiceRegistry 服务标识符

# src/YourBundle/Resources/config/services.php
<?php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $configurator): void {
    // ...
    $services->set(\App\YourBundle\Service\SomeYourServiceUsingRegistry::class)
        ->args([service('some.your.project.namespace.first.resource.registry')]);
};

声明您的服务

<?php
declare(strict_types=1);

namespace App\YourBundle;

use Highcore\Component\Registry\IdentityServiceRegistryInterface;

final class SomeYourServiceUsingRegistry
{
    public function __construct(private readonly Highcore\Component\Registry\IdentityServiceRegistryInterface $registry)
    {
    }

    public function someMethod()
    {
        // Retrieve all registered services
        $yourServices = $this->registry->all();

        // Use the services
    }