2
1

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 1 year has passed since last update.

Symfony ComponentAdvent Calendar 2022

Day 7

CLIツールを簡単に作れる、"Console"

Last updated at Posted at 2022-12-06

Symfony Component Advent Calendar 2022の7日目の記事です。

最初に

SymfonyはPHPのフレームワークのひとつです。しかし、公式サイトの説明文には

Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
(SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。)

と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。

今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。

※記事内ではautoloadのインポートは省略します。

CLIツールを簡単に作れる、"Console"

Consoleは、ターミナル(黒い画面)で実行するコマンドラインツールを簡単に作れるコンポーネントです。Symfony以外でも動作します。

インストール

composer require symfony/console

実行するコマンドラインを作る

まずは実行するためのコマンドラインを作ります。このコマンドラインを使って、別途作成するコマンドを実行します。

app.php
#!/usr/bin/env php

<?php

require __DIR__ . '/vendor/autoload.php';

use Symfony\Component\Console\Application;

$application = new Application;

// コマンド登録
...

$application->run();

コマンドを作る

次にコマンドを作ります。コマンドは Commandクラスを拡張した子クラスを作っていきます。

HelloCommand.php

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'app:hello',
    description: 'あいさつします',
)]
class HelloCommand extends Command
{
    protected function configure(): void
    {
        $this
            ->addArgument('name', InputArgument::REQUIRED, 'お名前') // 引数の設定
            ->addOption('with-date', 'd', InputOption::VALUE_NONE, '日にちを同時に表示します') // オプションの設定
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $name = $input->getArgument('name');

        $message = sprintf("こんにちは、%sさん。", $name);
        if ($input->getOption('with-date')) {
            $message .= sprintf("今日は、%sです。", (new \DateTime())->format('Y年m月d日'));
        }

        $io->success($message);

        return Command::SUCCESS;
    }
}

コマンドの設定については、Attributesで行います。#[AsCommand] Attributeを使い、コマンド名と概要を設定します。
引数やオプションについてはconfigure()メソッド内で定義します。引数はaddArgument(), オプションはaddOption()メソッドを実行して設定します。

そして、実際の処理はexecute()メソッド内に記述します。画面表示するメッセージはSymfonyStyleオブジェクトを使って表示します。
戻り値がintですが、実行結果によって、Command::SUCCESS(= 0), Command::Failure(= 1), Command::Invalid(= 2)を返します。

コマンドを実行する

作ったコマンドをadd()メソッドを使って、コマンドライン側に登録し実行できるようにします。

app.php
<?php

require __DIR__ . '/vendor/autoload.php';

use Symfony\Component\Console\Application;

$application = new Application;

// コマンド登録
$application->add(new HelloCommand()); // ここ

$application->run();

そして実行です。

php app.php app:hello すみだ

実行結果

 [OK] こんにちは、すみださん。

php app.php app:hello すみだ --with-date

実行結果

 [OK] こんにちは、すみださん。今日は、2022年12月07日です。                                                              

php 実行コマンドファイル {コマンド名} --{オプション}[={オプションの値}] {引数}、もしくはphp 実行コマンドファイル {コマンド名} {引数} --{オプション}[={オプションの値}] の順で記述すると、指定されたコマンド名に引数・オプションを渡して実行できます。上記の例では--with-dateに値を渡していませんが、これはInputOption::VALUE_NONEを指定したためで、これを指定するとオプション名がコマンドで指定された時点で、値としてtrueが入るようになっています。

Symfonyの場合

Symfonyの場合、実行コマンドは作る必要がなく、Symfonyインストール時に用意されたbin/consoleコマンドで実行できます。
また、各コマンドクラスはオートワイヤリングにより、コンストラクタに指定した引数が自動的にDIされます。すてき。

まとめ

今回はConsoleを紹介しました。このコンポーネント自体も強力ですが、Symfony内で使うとさらに強力です。
Symfony利用有無を問わず、コマンドラインツールを作成する際はぜひ使って欲しいコンポーネントです。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?