特集:「Composer」を語り合う
弊社で毎月開催し、PHPエンジニアの間で好評いただいているPHP TechCafe。
2022年6月のイベントでは「Composer」について語り合いました。
弊社のメンバーが事前にまとめてきたComposerの基礎知識や使い方の情報にしたがって、他の参加者に意見を頂いて語り合いながら学びました。
今回はその内容についてレポートします。
Composer とは
概要
プロジェクトの依存関係管理ツール
Composer の主な機能はプロジェクトの依存関係管理機能です。
プロジェクトで使用するパッケージの依存関係をまとめて管理することができます。
専用の設定ファイル (composer.json
) に必要なパッケージを定義してコマンドを実行するだけで、
プロジェクト内の vendor ディレクトリにパッケージがインストールされます。
つまり設定ファイルさえあれば、プロジェクト新規参入者でもコマンド1つで簡単に環境構築を行うことが可能です。
オートローディング
オートローディングとは読み込みたいファイルを include
/ requrire
することなく、
自動でファイルを読み込んでくれる機能です。
Composer では PSR-4 に基づいた名前空間を宣言します。
プロジェクト内の指定したディレクトリ配下を名前空間として使用可能にします。
公式ページ
Composer の公式ドキュメントやダウンロードは↓コチラです。
getcomposer.org
公式ページにアクセスすると指揮者のようなアイコンが表示されます。
Composer のアイコンはリロードするたびに色が変わります。
是非公式サイトにアクセスして試してみてください。
※※※ 稀にあまり目に優しくないチェック模様になります ※※※
アクセスするたびに色が変わることに気づいていたが、
バージョンによるものだと思っている方もいらっしゃいました。
使い方
基本的な使い方は公式ドキュメントに沿って、 monolog を例に説明されました。
1. composer.json を作成
Composer を導入したいプロジェクトに composer.json
という名前のファイルを作成します。
require
をキーとし、使用したいパッケージを vendor名/プロジェクト: バージョン
の形式で指定します。
使用したいパッケージの vendor 名やプロジェクト、バージョンについては Packegest というサイトで確認することができます。
monolog を指定する場合
{ "require": { "monolog/monolog": "3.1.*" } }
バージョンの指定には下記ルールが適用されます。
vX.Y.Z
またはX.Y.Z
で指定する- ワイルドカードが指定されている箇所は最新を取得するようにする
- 上記例では 3.1 系の最新が取得される
3.1.*
は>=3.1, < 3.2
と同じ意味- 詳細はコチラ
2. 依存関係のインストール
下記コマンドを実行することで composer.json
に定義されたパッケージがインストールされます。
php composer.phar update
このコマンドは大きく分けて2つの処理を行っています。
composer.lock
の作成 / 更新composer.json
を基にインストールするパッケージのバージョンを確定させる
- 暗黙的に
composer.phar install
を実行- vendor ディレクトリを作成して必要なパッケージを取得
composer.lock
の Git 管理について
composer.lock
は composer.phar update
コマンドで自動生成されるファイルです。
自動生成されるファイルを Git 管理するか否かはよく議論になるとおもいます。
composer.lock
を Git 管理するとよいケース/管理しないほうがよいケースについて、
それぞれ紹介されていました。
Git 管理するとよいケース
composer.lock
を Git 管理するとよいケースとして、パッケージのバージョンを固定したい場合が挙げられていました。
アプリケーション開発などでパッケージのバージョンを固定したい場面がよくあると思います。
composer.lock
はバージョンが明記されており、どの環境にも同一バージョンのパッケージをインストールすることが可能なため、
composer.lock
を Git 管理し、チーム内で共有することがおすすめされていました。
Git 管理しないほうがよいケース
composer.lock
の Git 管理をしないほうがよいケースとして、composer.lock の内容が都度変更される場合 が挙げられていました。
PHP の複数バージョン (5.4~8等) に対応したパッケージの開発ではバージョンごとで composer.lock
の内容が変わってしまいます。
そのため composer.lock
はあえて .gitignore
に入れ、都度 composer.phar update
することがおすすめされていました。
composer.lock
のコンフリクト対策
composer.lock
を Git 管理するという話から、
- 複数の開発する場合、
composer.lock
でコンフリクトが起きるケースがよくあります。
対応策などあったりしますか?
という質問がありました。
この質問に対して参加者から様々な解決方法が寄せられました。
composer.json
/composer.lock
を弄るときはさっさとメインブランチに入れる、が解だと思います- コンフリクトした人が master (main) から
composer require
/composer update
しなおす - ブランチごとに無関係のパッケージだったら
composer.lock
のコンフリクトだけなので気合で解消できる git rebase -i
が可能なら、git checkout HEAD composer.lock
で戻してからcomposer require
しなおします
また、「コンフリクトに対しては密なコミュニケーションが重要」や「神速でマージすれば問題ないのでは」といった意見も挙がりました。
Packegest
前述の通り、 Packegest は Composer で使用したいパッケージの情報を確認するサイトです。
Packegest では登録されているパッケージを利用するだけでなく、
自身で作成したパッケージを Packagest に登録することも可能です。
自作パッケージの登録方法
下記の4ステップで Packagest にパッケージを登録することができ、
非常に手軽だと参加者から驚きの声があがっていました。
1. composer.json 作成
Copmoser 利用時と同様に、まず composer.json
を作成します。
作成後、下記例のようにパッケージの詳細を記載します。
monolog の composer.json
{ "name": "monolog/monolog", "type": "library", "description": "Logging for PHP 8.0", "keywords": ["log","logging"], "homepage": "https://github.com/Seldaek/monolog", "license": "MIT", "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be", "role": "Developer" } ], "require": { "php": ">=8.0.0" }, "autoload": { "psr-0": { "Monolog": "src" } } }
Packagest の monolog ページと見比べて、どの設定がどの項目に反映されるかを確認してください。
2. コマンド実行
2つのコマンドを実行します。
1.composer.lock
更新
php composer.phar update
2.composer.json
の書式チェック
php composer.phar validate
3. GitHub 等に push
いつも通り、git push
してください。
4. Packagist に登録
最後に Packagest にログイン後、GitHub と紐づけます
登録の手軽さと怖さ
GitHub に push して紐づけてしまえばすぐに登録されるという手軽さから、
誰の査読も受けていないパッケージを登録できてしまうのが怖いという意見がありました。
これをきっかけに
「Packagest はパッケージ名にユーザ名や組織名が付くため、"だれが作ったかわからない" というリスクは少ないですね」
「npm などでは短い名前のデファクトっぽいパッケージ、例えば 〇〇 parser を適当に選んで使いがちですもんね」
「確かに 〇〇 parser って簡潔な名前だとそれが王道なのかなって思っちゃいますもんね」
「OSS 全体で言えることですが、より信頼できるパッケージを選びたいですね」
という話題で盛り上がりました。
private 版
Packagest の private 版も紹介されました。
有料にはなりますが、クラウド/自前のサーバどちらにもインストール可能です。
社内でオリジナルのパッケージを配布したいときに有効であるという意見がありました。
オートローディング
続いて Composer の主機能の1つであるオートローディングについて紹介されました。
オートローディングとは
まずはオートローディングとは?という基本的な説明が行われました。
オートローディングとは何度も include
/ requrire
しなくても自動的にファイルを読み込んでくれる機能です。
昔ながらのPHPプロジェクトでは include
や requrire
がズラーッと並ぶことが多いと思います。
シンプルなら問題ないですが、大半の場合はクラスごとに依存関係があるため読み込み順など管理が困難です。
<?php /** * 各ファイルから共通で読み込まれる */ namespace TechCafe; include_once __DIR__ . '/Hoge.php'; include_once __DIR__ . '/Fuga.php'; include_once __DIR__ . '/Piyo.php'; include_once __DIR__ . '/Hogera.php'; include_once __DIR__ . '/HogeHoge.php'; include_once __DIR__ . '/Foo.php'; include_once __DIR__ . '/Bar.php'; include_once __DIR__ . '/Baz.php'; include_once __DIR__ . '/Foobar.php'; // etc...etc...
そこで PHP には spl_autoload_register() というクラスローダを登録するメソッドが用意されています。
クラスローダとは引数に指定されたクラス名を読み込む機能を持った関数です。
spl_autoload_register()
には独自実装したクラスローダの関数名または無名関数をセットできます。
<?php /** * 各ファイルから共通で読み込まれる */ namespace TechCafe; // 無名関数でクラスローダをセット spl_autoload_register(function ($class) { include 'classes/' . $class . '.class.php'; });
難しく感じるかもしれませんが、include
/ requrire
の定義する代わりにを自動で読み込んでいるだけです。
Composer を使ったオートローディング
Composer を使えば、自前でクラスローダを実装することなくオートローディングを利用できます。
使い方
composer.json
に設定を追加し、コマンドを一度だけ実行します。
コマンド実行後は vendor/autoload.php
を読み込むだけでオートローディングを利用できます。
composer.json
{ "autoload": { "psr-4": { "TechCafe\\": "src/" } } }
コマンド実行
php ./composer.phar dump-autoload
autoload.php 読み込み
<?php /** * 各ファイルから共通で読み込まれる */ namespace TechCafe; require_once __DIR__ . '/../vendor/autoload.php';
spl_autoload_register()
の時のような独自実装もなく、
たったこれだけで include
/ requrire
地獄から解放されます。
クラス名とファイル名が必ずしも一致してない場合
上記設定でオートローディングを利用できますが、正常に読み込みが行われるのはクラス名とファイル名が一致している場合のみです。
既存プロジェクトでクラス名とファイル名が一致していない場合や、クラス名はキャメルケースだけどファイル名はスネークケースの場合等あると思います。
そんな場合は configmap
を定義することで対応可能です。
例)src/tools/test_util.php を読み込みたい場合
<?php namespace TechCafe class TestUtil { public static function getTest() { return "てすとだよ"; } }
composer.json
に classmap
を設定し、コマンドを実行します。
composer.json
{ "autoload": { "classmap": ["src/tools"], "psr-4": { "TechCafe\\": "src/" } } }
コマンド実行
php ./composer.phar dump-autoload
classmap
は有用ですが、デメリットもあります。
新しくクラスを追加した場合、psr4 で指定した場合はコマンドの再実行は不要ですが、
classmap
で指定した場合は再度 dump-autoload
を実行しなければクラスを読み込めません。
レガシープロジェクトなどでは難しいとは思いますが、
可能な限り、再実行の手間なく読み込むことができる psr-4 での指定が推奨されていました。
関数をオートローディングしたい場合
オートローディングに対応しているのは class や trait、interface のみです。
そのため global に定義された関数をオートローディングしたい場合は別途読み込む必要があります。
例)src/functions.php
に定義された getHoge()
を読み込みたい場合
<?php namespace TechCafe function getHoge() { return "Hoge!!"; }
composer.json
に files を設定することで対応可能です。
{ "autoload": { "classmap": ["src/tools"], "files": ["src/functions.php"], "psr-4": { "TechCafe\\": "src/" } } }
Composer オートローディングのパフォーマンス
通常ファイルの読み込みを行う場合、コロン区切りで指定されたディレクトリ (include_path) を順に走査を行います。
そのため、指定されたディレクトリの分だけ走査が行われパフォーマンスが悪くなっていました。
Composer のオートローディングはファイルの走査処理が最適化されており、
通常の読み込み処理に比べパフォーマンスが良くなっています。
また、Composer のオートローディングは遅延ロードとなっているのもパフォーマンス上でメリットといえます。
※遅延ロード:ファイルが必要になった時に読み込み処理を行うこと
例えば下記のような if 文があった場合、 $i
が numeric なら HOGE
が、そうでないなら FUGA
が読み込まれます。
<?php if(is_numeric($i)) { HOGE::getHoge(); } else { FUGA::getFuga(); }
参加者からは「レガシープロジェクトでも設定次第で Composer のオートローディングの恩恵を受けられるので適用したい」といった声があがっていました。
Composer2.0.0
最後に Composer 8年ぶりのメジャーバージョンアップである Composer 2.0.0 についての紹介です。
概要
- 2020/10/24 リリース
- 2012年のリリース以来初のメジャーバージョンアップ
- 参考資料
新機能や変更点
Performance improvements
Composer2 の大きな変更点としてパフォーマンスの改善が紹介されていました。
速度とメモリ使用量の両方が大幅に改善され、Composer1 と比べ 50% 以上の改善が見られたそうです。
この驚異的な改善に参加者から「これはすごい」「めちゃくちゃ速くなっている」という驚きの声があがっていました。
またパフォーマンス改善の要因として、パッケージ構造の変更による効率化が挙げられていました。
Architectural changes and determinism
require
/update
実行時の vendor ディレクトリ更新処理が中途半端に行われることが無くなりました。
Composer1 では更新中に LAN ケーブルが抜ける等でネットワークが切れた場合、
vendor ディレクトリが更新途中の状態になり復旧不可能になっていました。
Composer2 ではネットワークを跨いだ処理 (パッケージのダウンロード等) を全て終わらせてから更新を行うよう変更されたため、 更新中にネットワークが切れたとしても vendor ディレクトリが壊れることが無くなりました。
参加者からは「この機能は必須」や「更新するときの安心感が段違い」といった意見が寄せられていました。
Runtime features
オートロード時にプラットフォームチェック機能が追加されました。
vendor/autoload.php
が呼ばれた際、現在のPHPバージョンやエクステンションが対応したバージョンであるかをチェックし、一致していなければエラーにします。
Error reporting improvements
依存関係が解決できない場合に表示されるエラーの内容が改善されました。
Composer1 のエラー情報はごちゃごちゃしていたので、Composer2 で色がついたり見やすくなって嬉しいという意見がありました。
Partial updates with temporary constraints
特定のパッケージのバージョンを更新するためのコマンドが追加されました。
composer update vendor/package:1.0.*
↓では composer.json
や cmposer.lock
を更新したい場合は --with
を付ける
composer update --with vendor/package:1.0.*
ちなみに Composer1 でも required パッケージ名
を実行することで特定のパッケージを更新することができると紹介されていました。
編集後記
以上、Composer の概要と Composer2.0.0 の変更点について取り上げました。
Composer はパッケージの依存関係管理だけでなくオートローディングまで備えているため、
Composer を利用しない開発はありえないなと感じました。
Composer は現在でも4~5ヵ月ごとにマイナーバージョンアップされており、
積極的に開発が行われています。
今後も Composer の新機能や改善などに着目していきたいと思います!
「PHP TechCafe」では今後もPHPに関する様々なテーマのイベントを企画していきます。
皆さまのご参加をお待ちしております。
エンジニア中途採用サイト
ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
ご興味ありましたら是非ご確認をお願いします。
https://career-recruit.rakus.co.jp/career_engineer/
カジュアル面談お申込みフォーム
どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
以下フォームよりお申込みください。
rakus.hubspotpagebuilder.com
ラクスDevelopers登録フォーム
https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/
イベント情報
会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください!
◆TECH PLAY
techplay.jp
◆connpass
rakus.connpass.com