Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cycle orm migrations #25

Closed
wants to merge 16 commits into from
Closed
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"yiisoft/html": "^3.0@dev",
"yiisoft/security": "^3.0@dev",
"cycle/orm": "^1.1",
"cycle/annotated": "^2.0"
"cycle/annotated": "^2.0",
"cycle/migrations": "^1.0"
},
"require-dev": {
"hiqdev/composer-config-plugin": "^1.0@dev"
Expand Down
28 changes: 19 additions & 9 deletions config/common.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<?php

use App\Factory\CycleDbalFactory;
use App\Factory\CycleOrmFactory;
use App\Factory\LoggerFactory;
use App\Factory\MailerFactory;
use App\Helper\CycleOrmHelper;
use Cycle\ORM\ORMInterface;
use Psr\Log\LoggerInterface;
use Spiral\Database\DatabaseManager;
use Yiisoft\Aliases\Aliases;
use Yiisoft\Cache\ArrayCache;
use Yiisoft\Cache\Cache;
Expand All @@ -23,22 +26,18 @@
'@src' => '@root/src',
'@runtime' => '@root/runtime',
],
CacheInterface::class => [
'__class' => Cache::class,
'handler' => [
'__class' => ArrayCache::class,
],
],
Psr\SimpleCache\CacheInterface::class => ArrayCache::class,
CacheInterface::class => Cache::class,
LoggerInterface::class => new LoggerFactory(),
FileRotatorInterface::class => [
'__class' => FileRotator::class,
'__construct()' => [
10
]
],
\Swift_Transport::class => \Swift_SmtpTransport::class,
\Swift_SmtpTransport::class => [
'__class' => \Swift_SmtpTransport::class,
Swift_Transport::class => Swift_SmtpTransport::class,
Swift_SmtpTransport::class => [
'__class' => Swift_SmtpTransport::class,
'__construct()' => [
'host' => $params['mailer.host'],
'port' => $params['mailer.port'],
Expand All @@ -49,6 +48,17 @@
],
MailerInterface::class => new MailerFactory(),


// Cycle DBAL
DatabaseManager::class => new CycleDbalFactory(),
// Cycle ORM
ORMInterface::class => new CycleOrmFactory(),
// Cycle Entity Finder
CycleOrmHelper::class => [
'__class' => CycleOrmHelper::class,
'addEntityPaths()' => [
'paths' => $params['entityPaths'],
],
],

];
23 changes: 22 additions & 1 deletion config/console.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
<?php


use App\ConsoleCommand\CreateUser;
use App\Console\Command\CreateUser;
use App\Factory\CycleMigratorFactory;
use Psr\Container\ContainerInterface;
use Spiral\Migrations\Config\MigrationConfig;
use Spiral\Migrations\Migrator;
use Yiisoft\Aliases\Aliases;

$params = $params ?? [];

return [

CreateUser::class => CreateUser::class,

// Cycle Migrations
Migrator::class => new CycleMigratorFactory(),
// Migration Config
MigrationConfig::class => function (ContainerInterface $container) {
$aliases = $container->get(Aliases::class);
return new MigrationConfig([
'directory' => $aliases->get('@src/Console/Migration'),
'namespace' => 'App\Console\Migration',
'table' => 'migration',
'safe' => false,
]);
}
];
14 changes: 13 additions & 1 deletion config/params.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<?php

use App\ConsoleCommand\CreateUser;
use App\Console\Command\CreateUser;
use App\Console\Command\MigrateDown;
use App\Console\Command\MigrateGenerate;
use App\Console\Command\MigrateList;
use App\Console\Command\MigrateUp;

return [
'mailer.host' => 'smtp.example.com',
Expand All @@ -13,5 +17,13 @@

'commands' => [
'user/create' => CreateUser::class,
'migrate/generate' => MigrateGenerate::class,
'migrate/up' => MigrateUp::class,
'migrate/down' => MigrateDown::class,
'migrate/list' => MigrateList::class,
],

'entityPaths' => [
'@src/Entity'
]
];
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<?php


namespace App\ConsoleCommand;

namespace App\Console\Command;

use App\Entity\User;
use Cycle\ORM\ORMInterface;
Expand Down
77 changes: 77 additions & 0 deletions src/Console/Command/MigrateDown.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
namespace App\Console\Command;

use App\Helper\CycleOrmHelper;
use Spiral\Migrations\Config\MigrationConfig;
use Spiral\Migrations\MigrationInterface;
use Spiral\Migrations\Migrator;
use Spiral\Migrations\State;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MigrateDown extends Command
{
protected static $defaultName = 'migrate/down';

/** @var MigrationConfig */
private $config;

/** @var Migrator */
private $migrator;

/** @var CycleOrmHelper */
private $cycleOrmHelper;

/**
* MigrateGenerateCommand constructor.
* @param Migrator $migrator
* @param MigrationConfig $conf
* @param CycleOrmHelper $cycleOrmHelper
*/
public function __construct(Migrator $migrator, MigrationConfig $conf, CycleOrmHelper $cycleOrmHelper)
{
parent::__construct();
$this->config = $conf;
$this->migrator = $migrator;
$this->cycleOrmHelper = $cycleOrmHelper;
}

public function configure(): void
{
$this
->setDescription('Rollback last migration');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
// drop cached schema
$this->cycleOrmHelper->dropCurrentSchemaCache();

$list = $this->migrator->getMigrations();
$output->writeln('<fg=green>' . count($list) . ' migrations found in ' . $this->config->getDirectory() . '</fg=green>');

$statuses = [
State::STATUS_UNDEFINED => 'undefined',
State::STATUS_PENDING => 'pending',
State::STATUS_EXECUTED => 'executed',
];
try {
$migration = $this->migrator->rollback();
if (!$migration instanceof MigrationInterface) {
throw new \Exception('Migration not found');
}

$state = $migration->getState();
$status = $state->getStatus();
$output->writeln($state->getName() . ': ' . ($statuses[$status] ?? $status));
} catch (\Throwable $e) {
$output->writeln([
'===================',
'Error!',
$e->getMessage(),
]);
return;
}
}
}
54 changes: 54 additions & 0 deletions src/Console/Command/MigrateGenerate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
namespace App\Console\Command;

use App\Helper\CycleOrmHelper;
use Spiral\Migrations\Migrator;
use Spiral\Migrations\Config\MigrationConfig;
use Spiral\Migrations\State;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MigrateGenerate extends Command
{
protected static $defaultName = 'migrate/generate';

/** @var Migrator */
private $migrator;

/** @var CycleOrmHelper */
private $cycleHelper;

/** @var MigrationConfig */
private $config;

public function __construct(
Migrator $migrator,
MigrationConfig $conf,
CycleOrmHelper $cycleHelper
) {
parent::__construct();
$this->migrator = $migrator;
$this->config = $conf;
$this->cycleHelper = $cycleHelper;
}

public function configure(): void
{
$this->setDescription('Generates a migration');
}

protected function execute(InputInterface $input, OutputInterface $output): void
{
// check existing unapplied migrations
$list = $this->migrator->getMigrations();
foreach ($list as $migration) {
if ($migration->getState()->getStatus() !== State::STATUS_EXECUTED) {
$output->writeln('<fg=red>Outstanding migrations found, run `migrate/up` first.</fg=red>');
return;
}
}

$this->cycleHelper->generateMigration($this->migrator, $this->config);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wolfy-j suggested that such check is needed.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cycle will generate migrations based on diff with current DB schema if the schema is not consistent you will generate broken migrations. This is a small nasty issue, so such check is recommended.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand and support this recommendation. Also, it would be nice not to generate empty migrations

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... Why would empty migrations be generated?

Copy link

@wolfy-j wolfy-j Oct 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are checking if migration is required via Generator observer: https://github.com/spiral/framework/blob/master/src/Command/Cycle/MigrateCommand.php#L78

You are free to copy its code, it also gives you a nice description of what have changed.

https://github.com/spiral/framework/blob/master/src/Command/Cycle/Generator/ShowChanges.php

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1.0.5

Copy link
Member

@samdark samdark Oct 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question. How would it work if you write migration manually? Would that still create dummy migration classes for me?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ORM and manual migrations works using the same engine, you can combine them if you want. Basically ORM simply writes migrations for you, the rest is the same.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
54 changes: 54 additions & 0 deletions src/Console/Command/MigrateList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
namespace App\Console\Command;

use Spiral\Migrations\Config\MigrationConfig;
use Spiral\Migrations\Migrator;
use Spiral\Migrations\State;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MigrateList extends Command
{
protected static $defaultName = 'migrate/list';

/** @var MigrationConfig */
private $config;
/** @var Migrator */
private $migrator;
/**
* MigrateGenerateCommand constructor.
* @param Migrator $migrator
* @param MigrationConfig $conf
*/
public function __construct(Migrator $migrator, MigrationConfig $conf)
{
$this->config = $conf;
$this->migrator = $migrator;
parent::__construct();
}

public function configure(): void
{
$this
->setDescription('Print list of all migrations');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$list = $this->migrator->getMigrations();
$output->writeln('<fg=green>' . count($list) . ' migrations found in ' . $this->config->getDirectory() . ':</fg=green>');

$statuses = [
State::STATUS_UNDEFINED => 'undefined',
State::STATUS_PENDING => 'pending',
State::STATUS_EXECUTED => 'executed',
];
$list = $this->migrator->getMigrations();

foreach ($list as $migration) {
$state = $migration->getState();
$output->writeln($state->getName() . ' <fg=yellow>[' . ($statuses[$state->getStatus()] ?? '?') . ']</fg=yellow>');
}
}
}
Loading