phpの名前空間をお手軽に変えるライブラリ書いてた

表題の通り php名前空間IDEみたいに置き換えられるコマンド書いてました。

実をいうと割と前の話で、社内の勉強会とかでは喋ってたんですが、ちゃんとパブリックで書いてなかったので書きます。あれからちょこちょこアップデートもしたし

これなに

主に php名前空間を置き換えるためのコマンドです。IntelliJ とか使ってる人にはおなじみの機能だと思いますが、それを php スクリプトで実現した感じです。

基本的に必要なオプションは以下の3つです。

  1. composer.jsonのパス
  2. 変更前の名前
  3. 変更後の名前

変更前後の名前を入力するのは当然だと思いますが、composer.json のパスを読み込ませるのは解析対象にするファイルを知るためです。

つまり composer.json

    "autoload": {
        "psr-4": {
            "YourName\\": "src"
        },
        "files": ["src/functions.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "YourName\\": "tests"
        }
    },

と書いてあればその内容に従って src,tests,functions.php を解析対象にします。

なお、解析は nikic/PHP-Parser で行います。このライブラリについては qiita に書いたので興味あれば御覧ください。

正規表現とかではなくまともな方法で静的解析するので安定性はそれなりにある、と思います。

また、各ファイルの解析はマルチプロセスで並列実行されます。namae-space を作るにあたって、100%プレーンな php だけで動くように気をつけていたので速度面でちょっと不安がありましたが、並列実行にしたことによりまあまあ大丈夫なパフォーマンスになったような気がします。遅かったらすいません。php-cs-fixer よりはマシ、かも・・・。

ついでに言うとコードの内容を書き換えるだけではなくその名前のクラスを find する機能とかも乗っけています。そのあたりはリポジトリの readme を読んでみて頂ければ幸いです。

なんでつくったの

会社のリポジトリにグローバルな名前空間に作られたクラスが結構あってちょっとアレだったので、それを一息で殺すために作りました。もう2017年だし namespace ナシでクラス作る人はさすがにいないんですが、昔のコードにそういうのが残ってて殲滅したいなと思ってました。

先述の通り IntelliJ とかには名前空間を置き換える refactoring 機能がついていて、日頃から大変お世話になっているのですが、名前がグローバルだと置き換えられないんですよね。そういうわけで自分でスクリプト書きました。

便利オプション補足

一応 readme にも書いたんですが replace コマンドののオプションを一応ここにも載せます。以下は全て optional なので必要になったら参照して下さい。

-D:–dry_run

ドライランです。コードの置き換えは行わず diff だけ出力します。

-M:–max_process

静的解析の並列実行数を指定します。デフォルト10になっててちょっと強めかも。

-A:–additional_paths, -E:exclude_paths

先述の通り解析対象は composer.json を読み込んでよしなに出すんですが、お作法が違うディレクトリがあったりしたらそれらを強制的に加えたり外したりできます。グローバルな名前を置き換えたいとかいうニーズの場合このオプションが必要になるのではないでしょうか。

-R:–replace_dir

composer.json の内容だけでは新しい名前空間のファイルの置き場所が一意に決まらない場合があります。例えば先述した composer.json の内容で、YourName\Klass.php を作りたい場合、Klass.php は src 以下におけば良いのか tests 以下におけばいいのか厳密には判断できません。そうなった場合 namae-space はインタラクティブモードで「src と tests どっち使う?」と聞いてくるのですが、それをスキップしたい場合このオプションを使って直にファイルの置き場所を指定できます。

苦労話

gong023/namae-space はとにかく手軽に使えるものにしたくて、インストールgithub から phar を落とせば終わり、という形にしようかと思ってました。

しかし、phar だと proc_open が動かないんじゃないかという疑惑があり、このため phar による提供は一旦止めてます。

phar だと proc_open が動かないんじゃないかという疑惑

再現コードはこんな感じです。

gist.github.com

php をポチポチ gdb デバッグしてみると、なんかどうも この辺php phar://myphar… みたいな文字列が渡されていてそれを実行しようとするのでそりゃ動くわけないなって感じなんですが、これこういうもんなんでしょうか。

これだれか分かる人がいたら教えていただきたいです。