LoginSignup
4
1

PsySHをカスタマイズしよう

Last updated at Posted at 2023-12-17

PHP Advent Calendar 2023 の17日目の記事です!

Laravel tinkerでも利用されている PsySH のカスタマイズについて紹介します。

PsySH

いわゆる REPL(Read-Eval-Print Loop)環境です。
Laravelを使っている方はtinkerでおなじみですね。
tinkerはpsyshをラップしていて、psyshと同じカスタマイズ方法が可能です。

使い方は @rana_kualu さんのステキ記事 PsySH公式サイト日本語訳 #PHP - Qiita を読もう!

設定ファイル

設定ファイルの場所

ユーザのHomeディレクトリや、プロジェクトの基準ディレクトリに設定ファイルを書いておくと読んでくれます。
プロジェクト毎の設定はgit管理してチームで共有すると良いかも。

  • グローバル(ユーザ毎)設定
    • ~/.config/psysh/config.php
  • ローカル(プロジェクト毎)設定
    • プロジェクトの基準ディレクトリ/.psysh.php
      • ※グローバル設定を オーバーライド して拡張する

設定ファイルの書き方

phpファイルなので割りと自由に書けます。
ファイルの先頭に <?phpを書くのを忘れずに。

設定項目は公式ドキュメントのページを参照ください。

設定ファイルのサンプルは、公式や前述の@rana_kualu さんの記事を参考に。

プロンプトのカスタマイズ

デフォルトのプロンプトは > ですが、設定でカスタマイズできます。
例えば、Laravel tinkerを開発環境だけでなく、ステージング環境や本番環境でも扱う場合は、見分け易くするためにプロンプトを変えておくと良いかも。
私は以下のような設定をしています。

.psysh.php
<?php

return [
    'theme' => [
        // ローカル環境以外ではプロンプトに環境名を表示する
        'prompt' => ($_ENV['APP_ENV'] === 'local' ? '' : $_ENV['APP_ENV'] ) . '> ',
    ],
];

ローカル環境外では環境名を表示するので事故防止に役立てば良いな。

image.png

ページャーのカスタマイズ

折返しが読みにくい問題

長い文字列が折り返されて、とても読みにくいですね。

image.png

lessのオプションを変えよう

psyshではデフォルトのぺージャーとしてlessが使われています。
キーボードで - S と続けて入力すると、折り返さないモードで表示されます。

image.png

less内で毎回インタラクティブコマンドを叩くのも面倒なので、デフォルトの設定を変えましょう。
設定のpagerに、lessコマンドの好きなオプションをつけて設定しておきます。

以下のオプションは特に有用です。

  • -S 折り返さない
  • -R ANSI colorエスケープシーケンス対応 (色をつける)
  • --quit-if-one-screen 1画面に収まる場合はすぐ終了
.psysh.php
<?php

return [
    // ...

    // pager less
    //   -S  折り返さない
    //   -R  ANSI color escape sequence対応
    //   --quit-if-one-screen 1画面に収まる場合はすぐ終了
    'pager' => 'less -S -g -j10 -M -R -i --no-init --quit-if-one-screen --RAW-CONTROL-CHARS',
];

Vimをページャーとして使ってリッチな体験

Vimを使われている方なら、もっとリッチな検索や移動、編集、
折り畳みなどの高度な表示が欲しいと思うかもしれません。
いっそ、Vimをページャーにしてみましょう。

ポイントは以下です。

  • 読み込み専用viewコマンドを実行
  • Vim側でシンタックスハイライトする
    • 元の色付けしてあるエスケープシーケンスを削除
    • vimデフォルトのperlのシンタックス定義を使う
      • ※ファイルタイプ定義と色定義を自作で頑張るのは大変なので
      • キー名、文字列、数値などがそれなりに色付けされる
  • 終了時にvimの画面を残す (お好みで)
.psysh.php
<?php

return [
    // ...

    // pager vim
    //   sed "s/\x1b\[[0-9;]*m//g" ANSI color escape sequenceを削除
    //   -c "set filetype=perl" perlシンタックスハイライトが見やすい
    //   -c "set t_ti= t_te=" vim終了時に元画面を復帰させなない(vimの画面を残す)
    'pager' => 'sed "s/\x1b\[[0-9;]*m//g" | view -c "set filetype=perl" -c "set t_ti= t_te=" -',
];

やったー折り畳み放題だ!

image.png

Vimなので、好きなようにカスタマイズできます。
以下を意識して、あとはお好みで。

  • psyshのdump出力に合わせてインデントを2にする
  • 折り畳み方法はindent
  • 折返ししない
~/.vimrc
" インデント、タブ
set tabstop=2
set softtabstop=2
set shiftwidth=2
set expandtab
set smarttab
set autoindent
set smartindent

" 折り畳み
set foldmethod=indent
set foldlevel=50

" 折返ししない
set nowrap

" 行番号を表示する
set number

" 対応する括弧やブレースを表示する
set showmatch

" カラースキーマ
colorscheme darkblue

ダンプをカスタマイズ

オブジェクトのダンプが冗長すぎる問題

値をダンプする際に、そのプロパティや子要素を再帰的に表示するので、ダンプ出力はかなり冗長になるので、
あまり重要ではない項目で画面がいっぱいになりがちです。

image.png

カスタムCaster

psyがオブジェクトをダンプする際に Symfony\Component\VarDumper が利用されています。
psyshでは設定でcasterを定義することで、クラスに応じたダンプ出力方法をカスタマイズできます。

VarDumperのcaster用関数 varDumperCast()を書いて、
それを、 UserモデルとMessageモデルの共通の親クラスApp\Models\Baseに適用してみます。

.psysh.php
<?php

// VarDumper で出力する際に、オブジェクトのプロパティをフィルタリングする
function varDumpCast($object, $array)
{
    // 後方一致するキーを抽出
    $matchedKeys = array_filter(array_keys($array), function ($key) use ($array) {
        // キーを分解してプロパティ名を取得
        [, , $prop] = explode("\0", $key);

        // 以下なら残す
        //   - プロパティ名が `id`か`name`か末尾が`_id`
        //   - オブジェクト、配列
        return $prop === 'id'
            || $prop === 'name'
            || substr_compare($prop, '_id', -3) === 0
            || is_object($array[$key])
            || is_array($array[$key]);
    });

    // マッチしたキーのみを持つ配列を作成
    $filteredArray = array_intersect_key($array, array_flip($matchedKeys));

    return $filteredArray;
}


return [
    // ...

    'casters' => [
        'App\Models\Base' => 'varDumpCast',
    ],
];

めっちゃスッキリした!

image.png

他のアトリビュートをコンパクトに出したい

他のアトリビュートを完全に隠すのではなく、コンパクトに出したい場合は、
1行のjsonにして加えてあげたらどうでしょう。

varDumpCastを少し修正
function varDumpCast($object, $array)
{
    ...

    // return $filteredArray;
    return [
        // 1行のjsonサマリを追加
        "#" => json_encode($object->getAttributes(), JSON_UNESCAPED_UNICODE, 1),
        ...$filteredArray,
    ];
}

以下のように1行の長いjson文字列が表示されるようになりますが、折り返さない設定のページャーだったら邪魔にはならないでしょう。

image.png

モデル毎にcasterを使い分ける

casterはクラスに対して複数定義できるので、
モデル毎にcaster用関数を使い分けて、モデルに応じてもっと細かな制御をしても良いですね。

.psysh.php(各モデル毎にcasterを使い分ける)
    'casters' => [
        // 各モデル用に出力をカスタマイズ
        'App\Models\User' => 'App\Models\User::varDumpCast',
        'App\Models\Message' => 'App\Models\Message::varDumpCast',
    ],

最後に

それでも皆さん、良い年末を!
明日は @ockeghem センセです!

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