dittto/doctrine-entity-factories

允许 Doctrine 从工厂中拉取实体,而不是仅通过反射

1.0.1 2017-12-30 16:29 UTC

README

由于使用简单的 PHP 对象作为实体,Doctrine 是一个非常易于使用的 ORM。它通过反射实例化这些实体。然而,如果您想要使用依赖注入来依赖另一个对象的实体,那么您就只能使用设置器注入。

此代码允许您从工厂中拉取新实体,从而实现构造函数注入和更干净的代码。

如何使用

首先,安装此插件。

composer require dittto/doctrine-entity-factories

接下来,让我们为我们的实体创建一个工厂。这些需要实现 EntityFactoryInterface

<?php
namespace App\Entities\Factories;

use App\Entities\TestEntity;
use Dittto\DoctrineEntityFactories\Doctrine\ORM\Mapping\EntityFactoryInterface;
use Illuminate\Contracts\Validation\Validator;

class TestEntityFactory implements EntityFactoryInterface
{
    private $validator;

    public function __construct(Validator $validator)
    {
        $this->validator = $validator;
    }

    public function getEntity()
    {
        return new TestEntity($this->validator);
    }
}

使用 Doctrine 最常见的框架是 Symfony,但您也可以使用 Doctrine 与 Laravel。以下是如何在两者中使用它的说明。

使用 Laravel

要使用 Laravel 中的 Doctrine,您可以使用这个有用的插件

composer require laravel-doctrine/orm:1.3.*
php artisan vendor:publish --tag="config"

我们将使用一个自定义提供者和该插件中存在的提供者。自定义提供者如下

<?php
namespace App\Providers;

use App\Entities\Factories\TestEntityFactoryInterface;
use App\Entities\TestEntity;
use Dittto\DoctrineEntityFactories\Doctrine\ORM\Mapping\EntityFactoryAware;
use Dittto\DoctrineEntityFactories\Doctrine\ORM\Provider\AbstractEntityFactoryServiceProvider;

class EntityFactoryServiceProvider extends AbstractEntityFactoryServiceProvider
{
    public function registerEntityFactories(EntityFactoryAware $entityFactoryRegister)
    {
        $entityFactoryRegister->addEntityFactory(
            TestEntity::class,
            new TestEntityFactory($this->app->make('hash'))
        );
    }
}

此提供者延迟所有对象。您还可以通过扩展 register()provides()new TestEntityFactory 转换为另一个对象。

接下来,我们将提供者添加到主应用配置中

<?php
// config/app.php
return [
'providers' => [
        App\Providers\DoctrineServiceProvider::class,
        \Dittto\DoctrineEntityFactories\Doctrine\ORM\Provider\DoctrineServiceProvider::class,
    ],
];

最后,我们需要修改 doctrine 配置以使用我们的插件

<?php
return [
    'managers' => [
        'default' => [
            'meta' => env('DOCTRINE_METADATA', 'yaml_with_entity_factories'),
        ]
    ]
];

使用 Symfony

与 Symfony 的许多事物一样,我们可以使用配置来完成几乎所有的事情。

首先,我们需要告诉 Symfony 使用我们的元数据工厂而不是默认的 Doctrine 一个

# app/config/config.yml
doctrine:
    orm:
        entity_managers:
            default:
                class_metadata_factory_name: Dittto\DoctrineEntityFactories\Doctrine\ORM\Mapping\ClassMetadataFactoryWithEntityFactories

如果您使用多个实体管理器,这可能会略有不同,但您可能也理解如何让您的代码工作。

Laravel 允许我们通过其服务提供者轻松加载附加代码。对于 Symfony,我们将采取稍微不同的方法,并装饰 Doctrine 的 EntityManager。这两种方法的目标都是相同的 - 在 Doctrine 开始创建实体之前将其实体工厂添加到其中。

对于 Symfony,我们将添加一些新服务

services:
    dittto.doctrine_entity_factories.entity_factory_manager_decorator:
        public: false
        class: Dittto\DoctrineEntityFactories\Doctrine\ORM\Decorator\EntityFactoryManagerDecorator
        decorates: doctrine.orm.default_entity_manager
        arguments: [ "@dittto.doctrine_entity_factories.entity_factory_manager_decorator.inner" ]
        calls:
            - [addEntityFactory, ['App\Entities\TestEntity', '@app.entities.factory.test']]

    app.entities.factory.test:
        class: App\Entities\Factories\Testfactory
        arguments: ['@validator']

这里我们将使用 calls 定义来添加我们所需的实体工厂。第一个字段是要由工厂创建的实体的完整类名。

这里的命名空间看起来非标准,但这纯粹是为了与上面的示例绑定。

测试

此插件自带测试。要运行这些测试,克隆代码并导航到目录。然后运行以下命令

composer install
./vendor/bin/phpunit