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

问题描述 投票:0回答:2

我正在尝试在迁移(使用 Symfony 5.1.2 和 doctrine/migrations 3.0.1)中获取容器和通过它的服务。但是当我尝试基于 this example 像这样创建一个类时:

class Version20200717072537 extends AbstractMigration implements ContainerAwareInterface
{
    use ContainerAwareTrait;

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

...我尝试运行迁移,但出现

Call to a member function get() on null
错误。
所以出于某种原因容器是空的。

我还尝试用我在其中找到的实际

use ContainerAwareTrait;
函数替换
setContainer
,看起来
setContainer
函数从未被调用过。

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

symfony dependency-injection doctrine migration
2个回答
10
投票

如旧版本相关的评论文档中所述。但是现在你可以用

MigrationFactory
来做。

你需要创建你自己的

MigrationFactory
类,它会在你的迁移中注入一些服务。从 3.4 Symfony 开始,所有服务都是私有的,所以你不能从容器中获取它们。

doctrine_migrations.yaml

services:
    'Doctrine\Migrations\Version\MigrationFactory': 'App\Doctrine\Migrations\MigrationFactory'

迁移工厂

<?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;
    }
}

迁移

<?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
    }
}

-2
投票

很好的解决方案,但我在尝试拥有自己的界面以便在某些迁移文件中拥有一项特定服务时遇到问题。有谁知道我怎样才能让界面工作? “找不到接口“App\Doctrine\Migrations\SomeInterface””

这是我的界面文件:

namespace App\Doctrine\Migrations;

use App\Services\Service;

interface SomeInterface
{
    public function setService(Service $service);
}
© www.soinside.com 2019 - 2024. All rights reserved.