How to pass migrations_paths to doctrine:migrations:migrate?

1.2k views Asked by At

It's possible to define multiple paths, where migrations are stored:

doctrine_migrations.yaml

doctrine_migrations:
    migrations_paths:
        'App\Migrations': '%kernel.project_dir%/src/App'
        'AnotherApp\Migrations': '/path/to/other/migrations'
        'SomeBundle\Migrations': '@SomeBundle/Migrations'

Now I want to use use these paths separately, like this:

$ php bin/console doctrine:migrations:migrate --em=foo --migrations_paths="AnotherApp\Migrations"

But there is no migrations_paths parameter and I also haven't found anything else, that would sound like what I need.

How to pass a single path or a list of paths to doctrine:migrations:migrate?

1

There are 1 answers

0
dev-cyprium On

I'm pretty sure you could potentially do this, in the advanced section in their documentation, there's mention of a method to define a file cli-config.php. So what's stopping you from defining such a file with contents like so:

<?php
require 'vendor/autoload.php';

use Doctrine\DBAL\DriverManager;
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Configuration\Migration\YamlFile;

// $config = new PhpFile('migrations.php'); // Or use one of the Doctrine\Migrations\Configuration\Configuration\* loaders
$config = new YamlFile('database.yml');

$conn = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'memory' => true]);

return DependencyFactory::fromConnection($config, new ExistingConnection($conn));

So now you have a place where you can change the $config before passing it further, however, to make this look very clean, we can use the decorator pattern to define our version of the configs like so:

<?php
class CLIDecorator extends ConfigurationFile
{
  /**
   * @var YamlFile
   */
  private $config;

  private $args;

  public function __construct(YamlFile $file, $args)
  {
    $this->config = $file;
    $this->args = $args;
  }

  public function getConfiguration(): Configuration
  {
    $config = $this->config->getConfiguration();
    // I'm not sure if php has a nicer argv parser
    // but I'm leaving this up to the reader
    if ($this->getMigrationOpts()) {
      $config['migrations_paths'] = $this->parse($this->getMigrationOpts());
    }

    return $config;
  }

  final protected function parse($rawOpt)
  {
    $parts = explode("=", $rawOpt);
    return str_replace('"', '', $parts[1]);
  }

  final protected function getMigrationOpts()
  {
    foreach ($this->args as $arg) {
      if (str_starts_with($arg, '--migrations_paths')) {
        return $arg;
      }
    }

    return null;
  }
}

Finally our code will look like this:

<?php
$config = new CLIDecorator(new YamlFile('database.yml'), $argv);

$conn = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'memory' => true]);

return DependencyFactory::fromConnection($config, new ExistingConnection($conn));