PHP
CakePHP
cakephp3

CakePHPでシェルの一覧を改行して表示させる

CakePHPのバージョンによっては(今回、CakePHP3.2を対象)、シェルの一覧が増えた時に長くなってしまい見難くなってしまいます。今回その一覧表示をシェル名ごとに改行を入れて見やすく表示させてみましょう。

まずは再現

Docker環境にてmcomposer.pharが使える状況を作りました。Docker上でなくても良いのですが、様々な環境を簡単に作れるのでおすすめです。

CakePHP用のプロジェクトを作成します。

 php composer.phar create-project --prefer-dist cakephp/app:3.2.* test
 cd test

シェルが増えた状況を再現させるために、以下のように30個のシェルを作ってみました。

seq 30|xargs -I{} ./bin/cake bake shell hogehoge{}

hogehogeで始まる30個のシェルができました。

ls src/Shell/
ConsoleShell.php     Hogehoge12Shell.php  Hogehoge15Shell.php  Hogehoge18Shell.php  Hogehoge20Shell.php  Hogehoge23Shell.php  Hogehoge26Shell.php  Hogehoge29Shell.php  Hogehoge3Shell.php   Hogehoge6Shell.php   Hogehoge9Shell.php
Hogehoge10Shell.php  Hogehoge13Shell.php  Hogehoge16Shell.php  Hogehoge19Shell.php  Hogehoge21Shell.php  Hogehoge24Shell.php  Hogehoge27Shell.php  Hogehoge2Shell.php   Hogehoge4Shell.php   Hogehoge7Shell.php
Hogehoge11Shell.php  Hogehoge14Shell.php  Hogehoge17Shell.php  Hogehoge1Shell.php   Hogehoge22Shell.php  Hogehoge25Shell.php  Hogehoge28Shell.php  Hogehoge30Shell.php  Hogehoge5Shell.php   Hogehoge8Shell.php

この状況で、シェル一覧を表示すると以下のようになります。

./bin/cake
...
Welcome to CakePHP v3.6.5 Console
---------------------------------------------------------------
App : src
Path: /var/www/html/test/src/
PHP : 7.2.6
---------------------------------------------------------------
Current Paths:

* app:  src
* root: /var/www/html/test
* core: /var/www/html/test/vendor/cakephp/cakephp

Available Shells:

[Bake] bake

[DebugKit] benchmark, whitespace

[Migrations] migrations

[CORE] cache, help, i18n, orm_cache, plugin, routes, schema_cache, server, version

[app] console, hogehoge1, hogehoge10, hogehoge11, hogehoge12, hogehoge13, hogehoge14, hogehoge15, hogehoge16, hogehoge17, hogehoge18, hogehoge19, hogehoge2, hogehoge20, hogehoge21, hogehoge22, hogehoge23, hogehoge24, hogehoge25, hogehoge26, hogehoge27, hogehoge28, hogehoge29, hogehoge3, hogehoge30, hogehoge4, hogehoge5, hogehoge6, hogehoge7, hogehoge8, hogehoge9

To run an app or core command, type `cake shell_name [args]`
To run a plugin command, type `cake Plugin.shell_name [args]`
To get help on a specific command, type `cake shell_name --help`

[app]から始まる行にある、シェルが改行されずに表示されており見難いという状況が再現されました。

シェルごとに改行させる!

どのようにシェル名を表示しているかを./vendor/cakephpのファイルを探っていくと、CommandListShellクラスがその役割と担っていることが分かりました。このクラスを継承して、シェル一覧表示の部分のみをカスタマイズすれば良さそうです。

次に、どのようにCommandListShellクラスを呼ばず、継承させたクラスを呼ぶべきかを調べてみます。シェルの一覧が出る時(つまりCommandListShellクラスが呼ばれる時)というのは、

./bin/cake

と書いた時で、引数が渡されない時であることも分かりますので、ちょっとトリッキーかと思いますが、./config/bootstrap_cli.phpファイルの最後に下記のように記載しました。

if (count($argv) < 2) {
    $argv = array_merge($argv, ['custom_command_list']);
}

これにより、引数がないときにCustomCommandListShellが呼ばれるように修正し、CustomCommandListShellというクラスを./src/Shellディレクトリに設置しました。

<?php
namespace App\Shell;

use Cake\Shell\CommandListShell;
use Cake\Core\Configure;

class CustomCommandListShell extends CommandListShell
{
    protected function _welcome()
    {
        $this->out();
        $this->out(sprintf('<info>Welcome to CakePHP %s Custom Console</info>', 'v' . Configure::version()));
        $this->hr();
        $this->out(sprintf('App : %s', APP_DIR));
        $this->out(sprintf('Path: %s', APP));
        $this->out(sprintf('PHP : %s', phpversion()));
        $this->hr();
    }

    protected function _asText($shellList)
    {
        foreach ($shellList as $plugin => $commands) {
            sort($commands);

            if ($plugin == 'app') {
                $this->out(sprintf('[<info>%s</info>]', $plugin));
                foreach ($commands as $command) {
                    $this->out($command);
                }
            } else {
                $this->out(sprintf('[<info>%s</info>] %s', $plugin, implode(', ', $commands)));
            }

            $this->out();
        }

        $this->out('To run an app or core command, type <info>`cake shell_name [args]`</info>');
        $this->out('To run a plugin command, type <info>`cake Plugin.shell_name [args]`</info>');
        $this->out('To get help on a specific command, type <info>`cake shell_name --help`</info>', 2);
    }
}

これで、シェル一覧部分が、改行付きで表示されるようになります。

./bin/cake

Welcome to CakePHP v3.6.5 Yourmystar Custom Console
---------------------------------------------------------------
App : src
Path: /var/www/html/test/src/
PHP : 7.2.6
---------------------------------------------------------------
Current Paths:

* app:  src
* root: /var/www/html/test
* core: /var/www/html/test/vendor/cakephp/cakephp

Available Shells:

[Bake] bake

[DebugKit] benchmark, whitespace

[Migrations] migrations

[CORE] cache, help, i18n, orm_cache, plugin, routes, schema_cache, server, version

[app]
console
custom_command_list
hogehoge1
hogehoge10
hogehoge11
hogehoge12
hogehoge13
hogehoge14
hogehoge15
hogehoge16
hogehoge17
hogehoge18
hogehoge19
hogehoge2
hogehoge20
hogehoge21
hogehoge22
hogehoge23
hogehoge24
hogehoge25
hogehoge26
hogehoge27
hogehoge28
hogehoge29
hogehoge3
hogehoge30
hogehoge4
hogehoge5
hogehoge6
hogehoge7
hogehoge8
hogehoge9

To run an app or core command, type `cake shell_name [args]`
To run a plugin command, type `cake Plugin.shell_name [args]`
To get help on a specific command, type `cake shell_name --help`

これで、シェルの数が増えても分かりやすいよね。という話でした。カスタマイズ方法も分かったので、シェルの種類ごとにグルーピングして更に見やすくしたりと、単に改行だけでない変更もできるかと思います。