0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel】migrationファイル名から日付を取り除く

Last updated at Posted at 2021-11-01

##はじめに
今回は、表題の方法を解説していきます。

「2019_07_05_052836_create_users_table.php」が「____create_users_table.php」のようにスマートになり、マイグレーションの順序も簡単に変更できるようになります。

お急ぎの方は、手順からどうぞ。
また、完成物はGitHubにあります。

##環境
Laravel Framework 8.64.0

##動機
なぜ、こんなことをしたいと思ったのか?理由は主に二つあります。
###その1
Laravelのマイグレーションは、__ファイルの作成日時の順__に実行されます。そのため、外部キー制約などリレーションの関係があるテーブルを複数扱う際に、正しい順序で実行できずにエラーとなってしまうことが多々あるのです。

###その2
Laravelのデフォルトのファイル名形式は「yyyy_mm_dd_xxxxxx_*.php」となっています。 例えば、「2019_07_05_052836_create_users_table.php」のようなものです。

この形式のどこが問題かというと、エディタなどで長いファイル名が省略された際に、どのテーブルについてのファイルかが一眼で判別できないという点です。

##手順
###雛形の作成
はじめに、以下のコマンドを実行し、雛形を作成してください。(今回はmigrate:freshmigrate:refreshコマンドについてのみ解説します。他のコマンドに関してもベースは同じです。)

php artisan make:command ArtisanMigrateFreshCommand
php artisan make:command ArtisanMigrateRefreshCommand

/app/Console/Commandsの中にArtisanMigrateFreshCommand.phpArtisanMigrateRefreshCommand.phpがあれば成功です。なかった場合は、以下のコードを元に作成してください。

__ArtisanMigrateFreshCommand.php__
ArtisanMigrateFreshCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ArtisanMigrateFreshCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        return Command::SUCCESS;
    }
}

__ArtisanMigrateRefreshCommand.php__
ArtisanMigrateRefreshCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ArtisanMigrateRefreshCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        return Command::SUCCESS;
    }
}

###雛形をコーディング
次に作成されたそれぞれのファイルについてコードを記述していきます。

まず、コマンド名を決定します。php artisanの後にくる識別名です。こちらは任意のもので結構なのですが、migrate:freshmigrate:refreshとしてしまうと、エラーとなってしまいます。すでに用意されているものは使用しないようにしましょう。

ArtisanMigrateFreshCommand.php
  protected $signature = 'migrate:f {--seed}';
ArtisanMigrateRefreshCommand.php
  protected $signature = 'migrate:rf {--seed}';

{--seed}は、マイグレーションと同時にシーディングを行うかのオプションです。

次に、コマンドの説明を設定します。こちらはスルーしても問題ありません。
コマンドでphp artisan listと打ち、migrate:freshmigrate:refreshのdescriptionを確認します。

抜粋
php artisan list

.
.
.
migrate:fresh        Drop all tables and re-run all migrations
migrate:refresh      Reset and re-run all migrations

これらをそのまま流用します。

ArtisanMigrateFreshCommand.php
  protected $description = 'Drop all tables and re-run all migrations';
ArtisanMigrateRefreshCommand.php
  protected $description = 'Reset and re-run all migrations';

次に、本命の作業です。実行する処理を記述していきます。

handle()にてそれぞれ以下のようにコーディングしてください。(本来であれば共通する処理はまとめるべきなのですが、今回は省略しています)

ArtisanMigrateFreshCommand.php
// 先頭に記述
use Illuminate\Support\Facades\Config;

public function handle() {

    $config = Config::get('migration');
    $migrations = $config['files'];
    $base_path = $config['base_path'];
    $prefix = $config['prefix'];
    $suffix = $config['suffix'];

    $is_first = true;

    foreach ($migrations as $migration) {
    $path = $base_path . $prefix . $migration . $suffix;

    if ($is_first) {
        $cmd = 'migrate:fresh';
        $is_first = false;
    } else {
        $cmd = 'migrate';
    }

    $this->call($cmd, [
        '--path' => $path,
    ]);
    }

    if ($this->option('seed')) {
    $this->call('db:seed');
    }

    return Command::SUCCESS;
}
ArtisanMigrateRefreshCommand.php
// 先頭に記述
use Illuminate\Support\Facades\Config;

public function handle() {
    $config = Config::get('migration');
    $migrations = $config['files'];
    $base_path = $config['base_path'];
    $prefix = $config['prefix'];
    $suffix = $config['suffix'];

    $is_first = true;

    foreach ($migrations as $migration) {
    $path = $base_path . $prefix . $migration . $suffix;

    if ($is_first) {
        $cmd = 'migrate:refresh';
        $is_first = false;
    } else {
        $cmd = 'migrate';
    }

    $this->call($cmd, [
        '--path' => $path,
    ]);
    }

    if ($this->option('seed')) {
    $this->call('db:seed');
    }

    return Command::SUCCESS;
}

###カーネルさんに登録する
/app/Console/Kernel.phpに先ほど作成した二つのコマンドを登録します。

Kernel.php
protected $commands = [
    Commands\ArtisanMigrateFreshCommand::class,
    Commands\ArtisanMigrateRefreshCommand::class,
];

###設定ファイルの作成
マイグレーション対象となるファイルを一元管理するファイルです。/database/seeders/DatabaseSeeder.phpと同様の役割を担っている捉えておいてください。

/config/migration.phpを作成し、以下の雛形をコピペしてください。

migration.php
<?php

return [

    'files' => [
        
    ],

    'base_path' => 'database/migrations/',

    'prefix' => '____',

    'suffix' => '.php',

];

files配列内にファイル名を実行したい順に列挙していきます。例えば、

migration.php
'files' => [
    'create_users_table',
    'create_plans_table',

    'create_admins_table',
]

のような形です。

この形を取ることで、__順序や実行の可否の変更は容易に変更できる__ようになります。

###ファイル名を変更する
最後にファイル名を変更しましょう。

日付部分(yyyy_dd_mm_xxxxxx)を取り除き、先頭にアンダースコア(_)を4つ並べた____**.phpという形式にします。例えば、____create_users_table.phpのような形です。

なお、このアンダースコア4つというのは、/vendor内の次のコードによるものです。

Migrator.php
protected function getMigrationClass(string $migrationName): string
{
    return Str::studly(implode('_', array_slice(explode('_', $migrationName), 4)));
}

##おわりに
以下のコマンドをそれぞれ実行してみましょう!

php artisan migrate:fresh
php artisan migrate:fresh --seed
php artisan migrate:refresh
php artisan migrate:refresh --seed

エラーが出なければ、無事成功です。

エラーが出てしまった場合は、
Kernel.phpにコマンドが登録されているか」
config/migration.phpにファイルが設定されているか」
「ファイル名が適切に変更されているか」
「その他手順通りに進められているか」
「マイグレーションファイル自体にエラーの原因がないか」
などを確認してみてください。

##GitHub
今回作成したファイルをまとめました。参考にどうぞ。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?