LoginSignup
9
4

More than 5 years have passed since last update.

CakePHPのMigrationクラスを既存のクラス定義からジェネレートする

Posted at

既存のクラス定義からCakePHP3のマイグレーションを生成するジェネレータを作った。

プロパティが沢山あるクラスを作ってからマイグレーションクラスの叩き台を作ったりする時に使えると思う。

ジェネレータクラス


<?php

class MigratinoClassGenerator
{
  public function generate(string $className)
  {
    $ref = new ReflectionClass($className);
    $properties = $ref->getProperties();

    $migrationClass = new MigrationClass();

    foreach ($properties as $property) {
      $migrationClass->addColumn($property->getName());
    }

    return $migrationClass->generate($ref->getName());
  }
}

class MigrationClass
{
  private $columns = [];

  public function addColumn(string $name, $type = 'string')
  {
    $this->columns[] = [
      'name' => $name,
      'type' => $type,
    ];
  }

  public function generate(string $className)
  {
    $buf = [];

    $buf[] = '<?php';
    $buf[] = '';
    $buf[] = 'use Migrations\AbstractMigration;';
    $buf[] = '';
    $buf[] = 'class CreateProduct extends AbstractMigration';
    $buf[] = '{';
    $buf[] = '    public function up()';
    $buf[] = '    {';

    $tableName = strtolower($className);
    $buf[] = sprintf('        $this->table(\'%s\')', $tableName);

    foreach ($this->columns as $column) {
      $buf[] = $this->generateColumn($column);
    }

    $buf[] = '            ->create();';
    $buf[] = '    }';
    $buf[] = '';
    $buf[] = '    public function down()';
    $buf[] = '    {';
    $buf[] = '        $this->dropTable(\''. $tableName . '\');';
    $buf[] = '    }';
    $buf[] = '}';

    return join("\n", $buf);
  }

  private function generateColumn(array $column)
  {
    $template = <<<TPL
            ->addColumn('%s', 'string', [
                'default' => null,
                'limit'   => null,
                'null'    => false,
            ])
TPL;

    return sprintf($template, $this->camelCase($column['name']));
  }

  private function camelCase(string $input) {
    preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!',
                   $input,
                   $matches);

    $ret = $matches[0];
    foreach ($ret as &$match) {
      $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
    }

    return implode('_', $ret);
  }
}

実行方法

<?php

$g = new MigratinoClassGenerator();
echo $g->generate('Product'); // クラス名を指定する

出力結果

<?php

use Migrations\AbstractMigration;

class CreateProduct extends AbstractMigration
{
    public function up()
    {
        $this->table('product')
            ->addColumn('id', 'string', [
                'default' => null,
                'limit'   => null,
                'null'    => false,
            ])
            ->addColumn('code', 'string', [
                'default' => null,
                'limit'   => null,
                'null'    => false,
            ])
            ->create();
    }

    public function down()
    {
        $this->dropTable('product');
    }
}
9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4