pre/post-install-cmdはcomposerで使用できる便利なイベントで、composer install
した時に自動で実行することが可能。
そのためGitHubでリポジトリを共有してチーム開発する場合、初期に行いたいセットアップを含めておけば自動的に環境構築が行なえます。
今回GitHooksを利用して無駄なコミットを防ぐためのシェルスクリプトを書いたのでチームでcomposer install
時に使えるようにと色々調べていたら、composer.lockファイルが無いとpre/post-install-cmdが動かないことが分かったのでメモしておきます。
- このケースでは
composer update
でpre/post-update-cmdを使用する pre/post-autoload-dump
を使用してもOKcomposer install
はcomposer.lockからパッケージをインストールするコマンドcomposer update
はcomposer.jsonからパッケージをインストールするコマンド
新規プロジェクトでまだcomposer.lockが無い場合
まず前提として、このケースは「新規のプロジェクトを作成している段階でまだcomposer.lockファイルが生成されていない」という場合に限ります。
例えば既にプロジェクトがあり、GitHub等でcomposer.jsonと共にcomposer.lockが含まれている場合は再現されません。
「composer.lockファイルが無い」という点がキーになります。
JavaScriptで使うnpmやyarnの場合、外部ライブラリを使うケースが非常に多いです。
特にReactでの開発がデファクトスタンダードになっている今、バニラJSだけで開発を進めるケースのほうがレアですよね。
反面PHPは特にWordPress周りの場合、ほとんど外部ライブラリを使うことがありません。
僕も後述するPHP CodeSnifferやWordPressのコーディング規約、PHP Compatibilityぐらいしか使わないのでcomposer.jsonは毎回コピペして一気にcomposer installしている状況です。
期待する動作
例えば以下のようなcomposer.jsonを用意します。
{
"require-dev": {
"squizlabs/php_codesniffer": "*",
"wp-coding-standards/wpcs": "*",
"phpcompatibility/php-compatibility": "*"
},
"scripts": {
"post-install-cmd": [
"echo test message"
]
}
}
require-devにいくつかパッケージを指定しており、scriptsにpost-install-cmdとしてechoコマンドを仕込んでいます。
当然「test message」がcomposerのパッケージインストール終了後に出力される事を期待しています。
しかし実際には以下のようなログが表示されます。
% composer install
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
- Locking phpcompatibility/php-compatibility (9.3.5)
- Locking squizlabs/php_codesniffer (3.6.0)
- Locking wp-coding-standards/wpcs (2.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
- Installing squizlabs/php_codesniffer (3.6.0): Extracting archive
- Installing phpcompatibility/php-compatibility (9.3.5): Extracting archive
- Installing wp-coding-standards/wpcs (2.3.0): Extracting archive
3 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
どこにも「test message」が出力されていません。
pre/post-install-cmdをcomposer installで実行する対策
不審に思って既にパッケージは入っていますが、再度composer installを叩いてみました。
% composer install
> echo test message
test message
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating autoload files
なんと、出力されていますね・・・!
ここで次の仮説が立てられます。
- 初回のcomposer installでは実行されない
- vendorディレクトリが無いから実行されない
- composer.lockファイルが無いから実行されない
- 2と3両方
そこでとりあえず手っ取り早く、vendorディレクトリを削除して再度composer installを叩いてみました。
% rm -rf vendor
% composer install
> echo test message
test message
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 3 installs, 0 updates, 0 removals
- Installing squizlabs/php_codesniffer (3.6.0): Extracting archive
- Installing phpcompatibility/php-compatibility (9.3.5): Extracting archive
- Installing wp-coding-standards/wpcs (2.3.0): Extracting archive
Generating autoload files
出力されていますね。
次はvendorディレクトリを残したまま、composer.lockファイルを削除して試してみます。
% rm composer.lock
% composer install
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
- Locking phpcompatibility/php-compatibility (9.3.5)
- Locking squizlabs/php_codesniffer (3.6.0)
- Locking wp-coding-standards/wpcs (2.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
3 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
出力されていません。
つまりcomposer.lockファイルが無いとpre/post-install-cmdは動かないということになります。
composerのパッケージインストール系のコマンドおさらい
ここで改めてcomposer
コマンドを整理してみます、結論から言えばそもそも僕の使用方法が間違っていました。
composerのインストール関連コマンド
composerにはインストールに関連するコマンドが全部で3つあります。
composer install
今回使用したコマンドがこのcomposer install
ですが、このコマンドはcomposer.lockからパッケージをインストールするコマンドです。
つまりそもそもcomposer.lockが存在している前提で使用すべきコマンドです。
composer require
新規にパッケージをインストールするコマンドで、npm install
のような役割のコマンドです。
なにかパッケージをCLIからインストールする場合はcomposer require
を使うと覚えておけばOK。
composer update
composer update
はcomposer.jsonを元にパッケージをインストールするコマンドです。
つまり今回のような「新規プロジェクトを作成し、最初にcomposer.jsonに記述したパッケージをインストールする=composer.lockがまだ無い」というような場合はこのコマンドを使うのが正しいようです。
composer.jsonを元にcomposer.lockを生成する正しい手順なので、pre/post-install-cmdをpre/post-update-cmdに切り替えればきちんと動作します。
composer updateでpre/post-update-cmdを試す
それでは実際にcomposer update
コマンドで想定したように動くか確認してみます。
composer.jsonは以下のように修正しました。
{
"require-dev": {
"squizlabs/php_codesniffer": "*",
"wp-coding-standards/wpcs": "*",
"phpcompatibility/php-compatibility": "*"
},
"scripts": {
"post-update-cmd": [
"echo test message"
]
}
}
8行目をpost-update-cmdに編集してあります。
# composer.lockとvendorディレクトリが無いことを確認
% ls -la
total 16
drwxr-xr-x@ 5 braveryk7 staff 160 10 10 13:38 .
drwxr-xr-x@ 16 braveryk7 staff 512 10 10 13:33 ..
drwxr-xr-x@ 9 braveryk7 staff 288 10 10 05:33 .git
-rw-r--r-- 1 braveryk7 staff 22 10 9 23:36 .gitignore
-rw-r--r-- 1 braveryk7 staff 393 10 10 15:14 composer.json
# composer update実行
% composer update
Loading composer repositories with package information
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
- Locking phpcompatibility/php-compatibility (9.3.3)
- Locking squizlabs/php_codesniffer (3.6.0)
- Locking wp-coding-standards/wpcs (2.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
- Installing squizlabs/php_codesniffer (3.6.0): Extracting archive
- Installing phpcompatibility/php-compatibility (9.3.3): Extracting archive
- Installing wp-coding-standards/wpcs (2.3.0): Extracting archive
3 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
> echo test message
test message
# composer.lockとvendorディレクトリが正常に生成されている
braveryk7@braveryk7s-MacBook-Pro ghtest % ls -la
total 32
drwxr-xr-x@ 7 braveryk7 staff 224 10 10 16:27 .
drwxr-xr-x@ 16 braveryk7 staff 512 10 10 13:33 ..
drwxr-xr-x@ 9 braveryk7 staff 288 10 10 05:33 .git
-rw-r--r-- 1 braveryk7 staff 22 10 9 23:36 .gitignore
-rw-r--r-- 1 braveryk7 staff 393 10 10 15:14 composer.json
-rw-r--r-- 1 braveryk7 staff 7586 10 10 16:27 composer.lock
drwxr-xr-x 8 braveryk7 staff 256 10 10 16:27 vendor
ばっちり想定したようにcomposer.lockファイルとvendorディレクトリが生成され、test messageが表示されていますね!
npmと同じように「installで大丈夫でしょ」と思って曖昧に使ってしまっていんたんですが、composer
コマンドは以下のように使い分けると良さそうです。
composer update | composer.lockファイルが存在しない時 |
composer install | composer.lockファイルが存在する時(GitHubからcloneしてきた等) |
composer require | 新しくパッケージをインストールしたい時 |
公式リファレンスにも各種イベントについて記載がある
ここまで書いておいてアレですが、実は公式ドキュメント「Scripts – Composer」に各種イベントについて記述があります。
pre-install-cmd: occurs before the
install
command is executed with a lock file present.post-install-cmd: occurs after the
install
command has been executed with a lock file present.pre-update-cmd: occurs before the
update
command is executed, or before theinstall
command is executed without a lock file present.post-update-cmd: occurs after the
https://getcomposer.org/doc/articles/scripts.md#command-eventsupdate
command has been executed, or after theinstall
command has been executed without a lock file present.
これを見る限り、composer install
コマンドを叩いた時にcoposer.lockファイルが無い場合はcomposer update
が実行されるようです(composer.lockがない場合、実質的にcomposer update
のエイリアスになっている)
試してみましょう。
composer.jsonは先程と同じようにpost-update-cmdを記述しています。
# composer.lockとvendorディレクトリが無いことを確認
% ls -la
total 16
drwxr-xr-x@ 5 braveryk7 staff 160 10 10 17:42 .
drwxr-xr-x@ 16 braveryk7 staff 512 10 10 13:33 ..
drwxr-xr-x@ 9 braveryk7 staff 288 10 10 05:33 .git
-rw-r--r-- 1 braveryk7 staff 22 10 9 23:36 .gitignore
-rw-r--r-- 1 braveryk7 staff 389 10 10 17:40 composer.json
# composer.lockが無い状態でpost-update-cmdを記述してcomposer installを実行
% composer install
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
- Locking phpcompatibility/php-compatibility (9.3.5)
- Locking squizlabs/php_codesniffer (3.6.0)
- Locking wp-coding-standards/wpcs (2.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
- Installing squizlabs/php_codesniffer (3.6.0): Extracting archive
- Installing phpcompatibility/php-compatibility (9.3.5): Extracting archive
- Installing wp-coding-standards/wpcs (2.3.0): Extracting archive
3 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
> echo test message
test message
なんと、composer install
を叩いたらpost-update-cmdが実行されました。
という事でやはりcomposer install
はcomposer.lockファイルが存在しない場合composer update
を実行するということは間違いなさそうです。
つまりcomposer.lockファイルがない場合、pre/post-install-cmdが実行されないのはcomposer update
コマンドが実行されているからでしょう。
composerのpre/post-install or update-cmdのベストプラティクス
ここまで見てきたように、基本的には新規プロジェクトを作成する時に同時にコマンド一発で色々処理を走らせたい場合はpre/post-update-cmdを指定するのが良さそうです。
ただし先述したように既存のプロジェクトのリポジトリをクローンして環境再現をする場合はcomposer.lockが存在すると思うので、この場合composer install
を使うことになり当然pre/post-install-cmdが実行されます。
どちらの場合も実行したい場合には冗長ではありますが、pre/post-install-cmdとpre/post-update-cmdどちらも指定しておくのが一番でしょうか・・・。
pre/post-autoload-dumpを指定する
少しハック的ですが、composer install
またはcomposer update
時には必ずcomposer dump-autoload
が実行されます。
それを利用して、composer dump-autoload
のイベントであるpre/post-autoload-dumpを指定するのも一つの手です。
{
"require-dev": {
"squizlabs/php_codesniffer": "*",
"wp-coding-standards/wpcs": "*",
"phpcompatibility/php-compatibility": "*"
},
"scripts": {
"post-autoload-dump": [
"echo test message"
]
}
}
これでcomposer update
時も動きますし、composer.lockが無い時のcomposer install
時も動きます。
【PHP】pre/post-install-cmdはcomposer.lockが無いと動かない まとめ
色んなサイトで情報を集めましたが、「最初はとりあえずcomposer install
をする」のような書かれ方をすることが多く誤った認識でとりあえず使っている方が多いかも知れません、事実僕もそうでした笑。
しかし実際にはcomposer.lockファイルが存在しない場合、composer install
コマンドを叩いて実際に実行されるコマンドはcomposer update
でした。
composerはPHPを使った開発に無くてはならない便利なパッケージ管理が行えますが、しっかり理解して使うと更に便利に使えるのでこの辺の知識はぜひ覚えておきたいですね!
コメント