如何在 Symfony 5 迁移中使用容器(和服务)?

frz*_*bor 7 migration doctrine dependency-injection symfony

我正在尝试在迁移中获取容器 - 以及通过它提供的服务(使用 Symfony 5.1.2 和学说/迁移 3.0.1)。但是当我尝试根据这个例子创建一个类时:

class Version20200717072537 extends AbstractMigration implements ContainerAwareInterface
{
    use ContainerAwareTrait;

    public function postUp(Schema $schema) : void
    {
        $fooService = $this->container->get('app.foo');
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

...我尝试运行迁移,但出现Call to a member function get() on null错误。
所以由于某种原因容器为空。

我还尝试用我在其中找到use ContainerAwareTrait;的实际setContainer函数替换,看起来该setContainer函数从未被调用过。

我很确定一段时间前我能够根据我上面链接的示例从迁移中获取容器(可能在 Symfony 3 或 4 中?),但现在我不知道这是否是 Symfony 中的预期行为5,或者是一个bug,或者我做错了什么。

Iho*_*rov 9

如与旧版本相关的评论文档中所述。但是现在您可以使用MigrationFactory.

您需要创建自己的MigrationFactory类,它将在您的迁移中注入一些服务。从 3.4 Symfony 开始,所有服务都是私有的,因此您无法从容器中获取它们。

学说_migrations.yaml

services:
    'Doctrine\Migrations\Version\MigrationFactory': 'App\Doctrine\Migrations\MigrationFactory'
Run Code Online (Sandbox Code Playgroud)

迁移工厂

<?php

namespace App\Doctrine\Migrations;

use Doctrine\DBAL\Connection;
use Doctrine\Migrations\AbstractMigration;
use Psr\Log\LoggerInterface;

class MigrationFactory implements \Doctrine\Migrations\Version\MigrationFactory
{
    /** @var Connection */
    private $connection;

    /** @var LoggerInterface */
    private $logger;

    /**
     * @var SomeService
     */
    private $service;

    public function __construct(Connection $connection, LoggerInterface $logger, SomeService $service)
    {
        $this->connection = $connection;
        $this->logger     = $logger;
        $this->service = $service;
    }

    public function createVersion(string $migrationClassName) : AbstractMigration
    {
        $migration = new $migrationClassName(
            $this->connection,
            $this->logger
        );

        // or you can ommit this check
        if ($migration instanceof SomeInterface) {
            $migration->setService($this->service);
        }

        return $migration;
    }
}
Run Code Online (Sandbox Code Playgroud)

移民

<?php

declare(strict_types=1);

namespace App\Doctrine\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * Auto-generated Migration: Please modify to your needs!
 */
final class Version20200717112426 extends AbstractMigration implements SomeInterface
{
    private $service;

    public function setService(SomeService $service)
    {
        $this->service = $service;
    }

    public function getDescription() : string
    {
        return '';
    }

    public function up(Schema $schema) : void
    {
        // this up() migration is auto-generated, please modify it to your needs
    }

    public function postUp(Schema $schema): void
    {
        $this->service->someMethod();
    }

    public function down(Schema $schema) : void
    {
        // this down() migration is auto-generated, please modify it to your needs
    }
}
Run Code Online (Sandbox Code Playgroud)