既存のクラス定義から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');
}
}