I'm trying to get the container - and a service through it - in a migration (using Symfony 5.1.2 and doctrine/migrations 3.0.1). But when I try to create a class based on this example like this:
class Version20200717072537 extends AbstractMigration implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function postUp(Schema $schema) : void
{
$fooService = $this->container->get('app.foo');
//...
}
}
... and I try to run migrations, I get a Call to a member function get() on null
error.
So for some reason container is null.
I also tried replacing the use ContainerAwareTrait;
with the actual setContainer
function that I found in it, and it looks like the setContainer
function is never called.
I'm pretty sure some time ago I was able to get the container from the migrations (maybe in Symfony 3 or 4?) based on the example I linked above, but now I don't know if this is the expected behavior in Symfony 5, or a bug, or I am doing something wrong.
In Symfony, these useful objects are called services and each service lives inside a very special object called the service container. The container allows you to centralize the way objects are constructed. It makes your life easier, promotes a strong architecture and is super fast!
Database migrations are a way to safely update your database schema both locally and on production. Instead of running the doctrine:schema:update command or applying the database changes manually with SQL statements, migrations allow to replicate the changes in your database schema in a safe manner.
The Doctrine Migrations offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and powerful tool. In order to use migrations you need to do some setup first.
Well, entity is a type of object that is used to hold data. Each instance of entity holds exactly one row of targeted database table. As for the directories, Symfony2 has some expectations where to find classes - that goes for entities as well.
As mentioned in the comments documentation related to the old version. But now you can do it with MigrationFactory
.
You need to create your own MigrationFactory
class, which will inject some service into your migrations. Starts from 3.4 Symfony all services a private, so you can't get them from the container.
doctrine_migrations.yaml
services:
'Doctrine\Migrations\Version\MigrationFactory': 'App\Doctrine\Migrations\MigrationFactory'
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;
}
}
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With