BLOG

ブログ

2022/02/14 技術系

【Laravel】コマンドの作成について

この記事を書いた人 T.U

はじめまして、2021年4月に入社いたしましたT.Uです。
今回はLaravelのコマンド作成について記事を書きたいと思います。

業務の中で以下の要件を満たす必要がありました。

  • ステージング環境のデータベースに入っているデータを開発環境で確認可能にする
  • データの整形を行うため、CSV形式でデータ出力を可能にする

PostgreSQLの場合、以下のコマンドでSQLのクエリー結果をCSVに出力することは可能ですが、何度も行う場合はとても面倒に思います。

psql 接続情報など -c "SELECT * FROM users;" -A -F, > output.csv


そこで、コマンドを作成しデータベース上のデータをCSV出力できるようにしたので、備忘録も兼ねてLaravelでのコマンド作成についてまとめたいと思います。

コマンドの作成

まずは、サンプルとして簡単なコマンドを作成し説明します。
コマンドを実行し、新しいコマンドクラスを作成します。
作成が完了すると、app/Console/Commands配下にファイルが生成されます。

php artisan make:command SampleCommand

各プロパティとメソッドについて

ここからは先ほど作成したapp/Console/Commands/SampleCommand.phpを編集していきます。

signatureプロパティ

signatureプロパティには、コマンドの名前や使い方を記述します。

protected $signature = 'command:sample-command {message=Hello World : メッセージを指定}';

descriptionプロパティ

php artisan listを実行した際に表示される説明文を記述します。

protected $description = '引数で渡されたメッセージを表示するコマンド';

また、ヘルプを表示する際にも表示されます。

handleメソッド

コマンドが実行された時に行う処理を記述します。

public function handle()
{
    $message = $this->argument('message');
    $this->info($message);
}

上記のようにhandle()に記述し、コマンドを実行した場合以下のように出力されます。

# php artisan command:sample-command
Hello World.

# php artisan command:sample-command こんにちは
こんにちは

データベースのバックアップコマンドを作成する

コマンドクラスを作成

クラス名は、DatabaseDumpCommandとしてコマンドクラスを作成します。

php artisan make:command DatabaseDumpCommand

signatureプロパティとdescriptionプロパティを編集

protected $signature = 'database:database-dump {--zip}';

protected $description = 'データベースをバックアップするコマンド';

signatureプロパティで指定した{--zip}はコマンドを実行する際に、引数の指定がある場合はtrue、ない場合はfalseが取得できます。

# php artisan database:database-dump
false

# php artisan database:database-dump --zip
true

handleメソッドを編集

public function handle()
{
    # zipをオプション引数として受け取る
    $isZip = $this->option('zip');

    # 現在の日時を取得
    $carbonNow = Carbon::now();
    $outputTimestamp = $carbonNow->format('Ymd_Hi');

    # テーブルの一覧を取得
    $tables = DB::connection()->getDoctrineSchemaManager()->listTableNames();

    # 出力先のディレクトリを定義
    $basePath = sprintf("%s/backup/", storage_path());
    $outputPath = sprintf("%s/backup/%s/", storage_path(), $outputTimestamp);
    $zipPath = sprintf("%s/backup/zip/", storage_path());
    $zipFilePath = sprintf("%s%s.zip", $zipPath, $outputTimestamp);

    # 出力先のディレクトリが存在しない場合はディレクトリを作成
    if (!File::exists($basePath)) File::makeDirectory($basePath);
    if (!File::exists($outputPath)) File::makeDirectory($outputPath);
    if (!File::exists($zipPath)) File::makeDirectory($zipPath);

    foreach ($tables as $table) {
        # 出力先のCSVファイル名を定義
        $outputFilePath = sprintf("%s%s.csv", $outputPath, $table);
        # テーブルからすべてのデータを取得
        $data = DB::table($table)->get();

        # CSVファイルを生成
        $handle = fopen($outputFilePath, 'w');
        foreach ($data as $key => $row) {
            # 1件目の場合はkey値をCSVヘッダーを出力する
            if ($key === 0) {
                $keys = collect($row)->keys()->all();
                fputcsv($handle, $keys);
            }
            # key valueで入っているため、valueを取得する
            $values = collect($row)->values()->all();
            fputcsv($handle, $values);
        }
        fclose($handle);
    }

    $this->info('CSVファイルを作成しました');

    # コマンドライン引数としてzipが渡されている場合はZIPファイルを生成する
    if ($isZip) {
        # CSVファイルの一覧を取得
        $files = File::files($outputPath);

        # ZipArchiveインスタンスを生成
        $zip = new ZipArchive;
        if ($zip->open($zipFilePath, ZipArchive::CREATE) === true) {
            # CSVファイルをZIPに追加
            foreach ($files as $file) {
                $zip->addFile($file->getPathname(), $file->getFilename());
            }
            $zip->close();

            $this->info('ZIPファイルを作成しました');
        } else {
            $this->warn('ZIPファイルの作成に失敗しました');
        }
    }
}

作成したコマンドを実行

コマンドを実行すると、storage/backup/にCSVとZIPファイルが生成されていることを確認できます。

# php artisan database:database-dump      
CSVファイルを作成しました

# php artisan database:database-dump --zip
CSVファイルを作成しました
ZIPファイルを作成しました

まとめ

Laravelでのコマンド作成について紹介しました。
今回作成したコマンドを使うことで、簡単にデータを出力することが可能になったため、データの確認作業がとても楽になりました。

また、今回紹介した入力の取得以外にも、confirmメソッド(「はい」か「いいえ」の確認)やchoiceメソッド(選択肢から選択)など様々な入力や出力をする際に便利なメソッドがあります。
また、タスクスケジューリングを利用することで、作成したコマンドを定期的に実行することも可能です。



株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問い合わせ下さい!

アーカイブ