PHPでLaravelを触っていると、composer installというコマンドをよく見る。
何となく「必要なものをインストールするコマンド」だとは分かるけど、どこにインストールするんだろう。何回も実行したらどうなるんだろう。そもそも、PHPをアップデートするときもComposerを使うのか。
このあたりは、PHP本体とライブラリの役割を分けると、だいぶ整理しやすい。
この記事では、Composerの基本からcomposer.json・composer.lockの違い、installとupdateの使い分け、PHP CLI・PHP-FPMとの関係まで順番に見ていく。
前提はUbuntu 24.04などのLinux環境、Composer 2系、PHPを使ったWeb開発。説明中のPHP 7.4と8.4は複数バージョンを理解するための例で、Ubuntu 24.04に両方が標準で用意されているという意味ではない。コマンドは説明用のもので、ここで実行確認した記録ではない。
Composerとは? PHPのライブラリを管理するツール
Composer(コンポーザー)は、PHPの依存関係を管理するツールだ。
例えば、PHPから外部APIへHTTPリクエストを送りたいとき、通信処理をすべて自分で作る必要はない。Guzzleのような既存のライブラリを利用できる。
そのライブラリを追加するコマンドがこれ。
composer require guzzlehttp/guzzle
Composerは、必要なライブラリだけでなく、そのライブラリが利用する別のライブラリも調べ、条件に合うバージョンをインストールしてくれる。これが依存関係の管理ということ。
JavaScriptのnpm、Pythonのpipに近い役割だと思うと分かりやすい。
ただし、ここは最初に覚えておきたい。
- PHP:PHPのプログラムを実行する言語処理系
- Composer:PHPのプロジェクトで使うライブラリを管理するツール
- Laravel:PHPでWebアプリを作るためのフレームワーク
ComposerはPHP本体をインストール・更新するためのものではない。
Composerはどこにインストールする? vendorと3つのファイル
Laravelなどのプロジェクトでcomposer installを実行すると、通常はそのプロジェクト内のvendor/ディレクトリに依存ライブラリが配置される。
例えば、/var/www/example-appにプロジェクトがあるとする。
cd /var/www/example-app
composer install
標準的な構成はこんな感じ。
/var/www/example-app/
├── app/
├── public/
├── composer.json
├── composer.lock
└── vendor/
├── autoload.php
├── composer/
└── (依存ライブラリのディレクトリ)
大事なのは次の3つ。
| 名前 | 役割 |
|---|---|
composer.json |
必要なライブラリと、許可するバージョンの条件を書く |
composer.lock |
依存関係を解決した結果、実際に使うバージョンを記録する |
vendor/ |
インストールされたライブラリと自動読み込み用のファイルを置く |
例えばcomposer.jsonが「Guzzleの7系を使いたい」と指定し、composer.lockが「実際には7.x.yを使う」と記録するイメージ。数字の7.x.yは説明用だ。
vendor/autoload.phpは、ライブラリのクラスなどをPHPから自動で読み込むために使われる。
一般的なアプリでは、composer.jsonとcomposer.lockをGitで管理し、vendor/はGitに入れず、デプロイ先でcomposer installして再現する。
なお、vendor/は設定で別の場所に変えられる。またcomposer global requireは、プロジェクト内ではなくComposerのグローバル環境にパッケージを追加するコマンドなので別の話になる。
composer installは何をする? 何度も実行していい?
composer installは、プロジェクトに必要な依存ライブラリを、指定された状態にそろえるコマンド。
composer.lockが存在すれば、原則としてそこに記録されたバージョンを使う。
composer install
すでに必要なパッケージがそろっている場合は、例えばこんな表示になる。
Installing dependencies from lock file
Nothing to install, update or remove
Generating autoload files
つまり、何度実行しても、毎回同じライブラリを追加し続けるわけではない。
ただし、完全に何もしないという意味でもない。自動読み込みファイルの再生成や、composer.jsonで設定されたスクリプトの実行が行われる場合はある。
| 状況 | composer installの動き |
|---|---|
vendor/がない |
依存ライブラリをインストールする |
vendor/がそろっている |
通常、追加・更新・削除は発生しない |
composer.lockが変更された |
lockの状態に合わせて必要な変更をする |
composer.jsonはあるがlockがない |
依存関係を解決してインストールし、lockを作成する |
composer.jsonがない |
基本的に実行できない |
vendor/内の個別ファイルを手動で消した場合などは、composer installだけで必ず修復できるとは限らない。ライブラリのファイルを直接編集・削除しないほうがいい。
空のディレクトリで実行したら?
例えば、次のような操作。
mkdir sample-app
cd sample-app
composer install
その場所にcomposer.jsonがなければ、Composerは何をインストールするのか判断できない。通常はcomposer.jsonが見つからないというエラーになる。
新しくComposerの設定を作りたいならcomposer initを使う。
composer init
Laravelの新規プロジェクトを作りたい場合は、空のディレクトリで次のコマンドを使う方法もある。
composer create-project laravel/laravel .
最後の.は「現在のディレクトリ」という意味。installとcreate-projectでは役割が違うんだね。
composer installとcomposer updateの違い
この2つは似ているけど、目的が違う。
| コマンド | 何を基準にする? | 主な用途 |
|---|---|---|
composer install |
原則composer.lockに固定されたバージョン |
環境構築・デプロイ |
composer update |
composer.jsonの許可条件を使って依存関係を再解決 |
ライブラリの更新 |
例えば、composer.jsonに次の指定があるとする。
{
"require": {
"guzzlehttp/guzzle": "^7.0"
}
}
^7.0は7.0以上、8.0未満のバージョンを許可する指定だ。
composer.lockにあるバージョンが固定されていれば、composer installでは基本的にそのバージョンを使う。一方、composer updateでは条件の範囲内で新しいバージョンを選び直し、composer.lockを更新する。
# lockに記録された構成を再現する
composer install
# 依存関係を再解決してlockを更新する
composer update
# 特定のライブラリを対象に更新する
composer update guzzlehttp/guzzle
composer updateを実行すれば、必ずすべてが最新版になるわけではない。composer.jsonの条件や、ほかのライブラリとの互換性によって選べる版が決まる。
基本的には開発環境で依存関係を更新・検証してlockをコミットし、本番環境ではcomposer installで再現する使い方が分かりやすい。
composer.jsonの「php」はPHP本体のインストール指定ではない
ここは勘違いしやすいところ。
composer.jsonには、こんな記述もある。
{
"require": {
"php": "^8.4",
"guzzlehttp/guzzle": "^7.0"
}
}
"php": "^8.4"は、PHP 8.4以上、9.0未満の環境が必要という条件を示している。
composer updateしても、PHP 8.3が自動で8.4になるわけではない。現在のPHPが条件を満たしていなければ、依存関係のチェックでエラーになることがある。
PHP本体は、UbuntuならAPTなど、OSや実行環境側の仕組みでインストール・更新する必要がある。
拡張モジュールも同じ。例えば"ext-pgsql": "*"という指定はPostgreSQL用のPHP拡張が必要という意味であって、Composerがphp8.4-pgsqlをAPTでインストールしてくれるわけではない。
PHP本体・拡張モジュールは、Composerでは**「すでに実行環境に存在するはずのもの」**として扱われる。
PHP 7.4と8.4が共存するとき、Composerはどっちを見る?
Ubuntuのような環境では、異なるPHPのバージョンを共存させることができる。
例えば、PHP 7.4と8.4のCLIが両方入っている場合。
php -v # デフォルトのPHP CLI
php7.4 -v # PHP 7.4 CLI
php8.4 -v # PHP 8.4 CLI
php -vに表示されるのは、そのコマンドが参照しているデフォルトのPHP CLI。インストールされているPHPを全部表示するコマンドではない。
APTなどによる一般的なUbuntuの構成なら、次のコマンドでCLIの切り替え候補を確認できる。
sudo update-alternatives --config php
ただし、これはそのバージョンがupdate-alternativesに登録されている場合の話。
ここからが少しややこしいところで、Webサイトが使うPHPは別に決まることがある。
ターミナル
└─ PHP CLI(例:PHP 8.4)
└─ Composerが動作し、vendor/を管理
ブラウザ
└─ Apache
└─ PHP-FPM(例:PHP 7.4)
└─ LaravelなどのWebアプリを実行
ApacheがどのPHP-FPMに接続するかは、Webサーバー側の設定で決まる。したがって、php -vが8.4でも、Webサイトは7.4で動いている可能性がある。
Composerの依存関係チェックでは、基本的にComposerを実行しているPHP CLIのバージョンが使われる。 つまり、CLIとPHP-FPMでPHPのバージョンが異なると、Composerのチェックは通ってもWeb側で問題が出る場合がある。
例えばCLIとWeb側をそろえて使いたいなら、Composerを動かすCLIと、Webサーバーが接続するFPMを両方確認したい。
composer check-platform-reqsで、インストール済みライブラリに対する現在のCLI実行環境のPHP・拡張の条件を確認できる。Webで使うPHP-FPMまで自動で検査してくれるわけではない。
php -v
composer --version
composer check-platform-reqs
補足として、composer.jsonのconfig.platformには依存関係の解決用に仮のPHPバージョンを設定する機能もある。ただし、それも実際のPHPを変更するものではない。check-platform-reqsはその仮設定を無視して実環境を検査する。
PHP CLIとPHP-FPMの更新については、別の記事「PHP 8.4.27への更新手順:UbuntuでCLIとWebの両方を確かめる」でも整理している。
PHPとLaravelのバージョンは別に考える
PHP 7.4とLaravel 7.4は、同じ「7.4」でも別のソフトウェアのバージョンだ。
LaravelはPHPで動くフレームワークなので、使いたいLaravelのバージョンが、実行するPHPのバージョンに対応している必要がある。
例えばLaravel 7系のような古いフレームワークをPHP 8.4で動かせるとは限らない。要求するPHPのバージョン条件を満たさないとComposerでインストールできないし、条件を無視して入れても正常に動作する保証はない。
確認したいのはこの2点。
- Laravel本体が要求しているPHPのバージョン
- Laravelが依存するライブラリやPHP拡張の対応状況
PHPをアップデートする前に、composer.jsonとLaravelの公式アップグレードガイドを確認するのが安全だと思う。
よく使うComposerコマンド一覧
| コマンド | 役割 |
|---|---|
composer --version |
Composer本体のバージョンを確認 |
composer init |
composer.jsonを新規作成する |
composer install |
依存ライブラリをインストールする |
composer update |
依存ライブラリを更新する |
composer require パッケージ名 |
新しい依存ライブラリを追加する |
composer remove パッケージ名 |
依存ライブラリを削除する |
composer show |
インストール済みパッケージを確認する |
composer outdated |
更新候補を確認する |
composer validate |
composer.jsonやlockの整合性を確認する |
composer check-platform-reqs |
実際のPHP CLI・拡張が必要条件を満たすか確認する |
composer audit |
既知の脆弱性などを調べる |
Laravelなどの本番環境へのデプロイでは、よく次のように実行する。
composer install --no-dev --optimize-autoloader
--no-devは開発専用の依存ライブラリをインストール対象から外し、--optimize-autoloaderはクラスの自動読み込みを最適化する指定だ。
Composerのインストール処理ではプロジェクトが定義したスクリプトも実行されることがあるので、特に本番環境では実行内容を確認しておきたい。安易にsudo composer installしないことも大事。
まとめ:PHPを更新するのとComposerを更新するのは別
最後に、今回の話をまとめる。
| やりたいこと | 主に使うもの |
|---|---|
| PHP本体のバージョンを上げたい | APTなど、PHPを導入した仕組み |
| PHP-FPMのバージョンを変えたい | FPMのインストールとWebサーバー設定 |
| Laravelなどの依存ライブラリをそろえたい | composer install |
| ライブラリのバージョンを更新したい | composer update |
| プロジェクトが必要とするPHPの条件を変えたい | composer.jsonを変更し、互換性を検証 |
| Composer自体を更新したい | Composerの導入方法に対応した更新手段 |
PHPは実行するもの、Composerはライブラリを管理するもの。
この2つの役割を分けるだけで、composer installを何度実行していいのか、PHPを上げるときに何を変更するのか、複数のPHPを入れたときにどちらが使われるのかも考えやすくなる。
Laravelを扱うなら、composer.json・composer.lock・vendor/の3つをセットで理解しておくと、環境構築やデプロイでかなり役立つはず。