Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
235
Help us understand the problem. What is going on with this article?
@KEINOS

逆引き!Composer コマンド・ライン一覧 と 基礎知識

🐒 【2020/11/18 追記】2020/10/24 に Composer の v2 がリリースされました
速度改善、PHP 7.4 以降対応、パッケージ名の厳命化、composer 経由の PEAR 利用の終了など変更点が盛り沢山です。そのため、急に動かなくなるパッケージが出てきています。パッケージマネージャー、Docker や CI などで composer を自動インストールしている人はデフォルトで v2 になるので要注意です。
各種主要パッケージの追随が落ち着くまでの間、composer 本体のインストールや更新は下記のように --version オプションでバージョンを指定(固定)してください。

composerのインストーラーでv1.10.17に固定する例
composer-setup.php --version=1.10.17 
既存のcomposerのバージョンを変える・固定する例
composer self-update 1.10.17

PHP のパッケージマネージャー Composer

この記事は、Composer のコマンド・ライン逆引き辞書です。

🐒  「LGTM」(旧いいね)が付くたびに何かしら見直して手を加えています。変更通知は送りませんので「ストック」されても変更に気づかれないかもしれません。お手すきに気が向いたら、また覗きに来てください。追加・誤記修正・同じコマンドの別表記など、何かありましたら遠慮なく編集リクエスト下さい。ほぼ自動で反映させます。

まえがき

曰く

composer.json の require を直接編集してはいけない」by @tadsan @ Qiita

つまり、専用のコマンドがあるのに composer.json を直接エディタで編集するのはバッドノウハウ。専用のコマンドがあるのに、素人にエディタで編集させる記事はバッドメディシン

コマンド・ラインで追記する例
$ # 文法
$ #   composer require [vendor]/[package]
$ # 使用例
$ composer require symfony/console

餅は餅屋に任せた方が安心でうまいということ。JSON からエスケープなんて怖いこと考えなくていいので安全ということ。

🐒   ただ Composer の中の人たちは「JSON なんだから何でも CLI で変更させる必要はないんだ、マイフレンド」というスタンスのようで、autoload などの設定はコマンド・ラインからは追加できません。(´・ω・`)

README.md
  • 本記事は composer.pharcomposer とリネームして事前にパスを通すことを前提としています。
  • パスを通していない場合は $ composer [hoge] の箇所を $ php /path/to/your/composer.phar [hoge] など、composer.phar の実際の設置先と置き換えて下さい。
  • $ composer$ 付き表記はコマンド・ラインでの入力例です。
  • ユーザー指定の必須項目は [] で囲っています。

    フォーマットと実際の記述例
    $ # composer require [vendor]/[package]
    $ composer require keinos/project_x
    
  • デフォルトの設定として登録する場合は global オプションをつけてください。

    現在のパッケージに適用
    $ # global なし → ./vendor/ 下にインストールされます
    $ composer require keinos/project_x
    $ # global あり → ~/.composer/vendor/ 下にインストールされます
    $ composer global require keinos/project_x
    
  • composer.json のある作成中のアプリ(ライブラリ、プロジェクト、etc)は「自身のパッケージ」と呼んでいます。(Rootパッケージ = 自身のパッケージ)


逆引き一覧

composer 本体

ダウンロードとインストール

composer 自体(本体)をダウンロードしたい

本家(composer 公式)のサイト上部にある php から始まる 4 行を実行してダウンロードします。(王道)

Download Composer @ Composer 公式

どれ?他に別途必要なものは?

スクリーンショット 2019-12-10 11.15.30.png

上記4行を実行すると composer.phar ファイルがカレント・ディレクトリに作成されます。内容としては、composer-setup.php をダウンロードして、ファイルのハッシュ値を検証したのち、OS や PHP のバージョンに合わせた composer.phar をダウンロードします。

途中、チョロリと見えているハッシュ値は、リリースごとに変わるので、CI や Docker などの自動インストールには向きません。後述するシェル・スクリプトなどから composer 本体をダウンロードする方法各種をご覧ください。

また、この場合は composer の本体である composer.phar がカレント(現在の)ディレクトリに設置されるため、実行するたびに composer.phar ファイルをパスで指定する必要があります。

ダウンロードしたcomposerの実行例
$ ./composer.phar --version
$ php ./composer.phar --version
$ php /path/to/downloaded/composer.phar --version

インストール、つまりパスを通したい場合は次項の「composer コマンドをどこからでも実行できるようにしたい」を参照してください。

🐒 【注意】 たまにcomposer.phar のダウンロードは「curl -sS https://getcomposer.org/installer | php だけでおk」と案内しているブログ記事がありますが推奨されていません。これには、重要な2つの理由があります。

1つ目は不正な composer 本体を使った場合、インストールされるパッケージ全てが信用出来なくなるからです。推奨されているどの方法も、インストーラーと、その署名(signagure)を別のドメインからダウンロードしていることに注目ください。

2つ目は、ダウンロード時にファイルの一部が壊れてしまうも、主な機能に支障がなく、気付かないで使い続ける事を避けるためです。PHP は Web を主体としていたため、致命的でない限り止まることより動くことを優先して来ました。そのため、一部が壊れてしまっても動いちゃう事が多くあります。これは意図しない不具合を発生する事にもつながり、パッケージの作者に「バグだバグだ」と再現性のない不具合を報告しない為にも、最初のステップでしっかりとハッシュ値が合っているか確認しましょう。
ハッシュ関数を使って確認している理由が知りたい方は、下記記事の「ハッシュ関数の基本と特徴」をご覧ください。

Composer 自体の依存(Requirements

composer.phar 自体は PHP v5.3.2 以上が利用可能であれば単体で動きます。しかし、条件によって unzipgit といったパッケージ管理に必要なツールを別途インストールする必要があります。

いずれのツールも、必要かつインストールされていない場合は composer 利用時にエラーで知らせてくれます。もしくは composer diagnose コマンドで確認することもできます。

ZIP 解凍ツール

composer はパッケージの解凍に zip/unzip を必要とします。Windows の場合は PHP の ZipArchive が使われますが、Linux/macOS の場合は、zlib モジュールに実行権限問題が発生することがあるため unzip コマンドを別途インストールすることが推奨されています。権限の問題で別途必要な場合は、メッセージが表示されます。

バージョン管理ツール

パッケージを zip アーカイブでインストールせず、PackagistVCS(バージョン管理システム)のリポジトリからインストールする場合、利用している VCS のパッケージ管理コマンド・ツールをインストールします。

composer は以下の VCS に対応しています。特に利用するリポジトリの種類が決まっていない場合は、Packagist、GitHub や GitLab などの相性を考えて git をインストールすることを個人的(筆者は)オススメします。

  • git svn fossil hg

composer コマンドを、どこからでも実行できるようにしたい

パスの通ったディレクトリに「拡張子なし」で設置してインストールします。(以下は Linux / Unix / macOS / Windows WSL2 の bash)

$ # カレント・ディレクトリに composer.phar があるか確認
$ ls ./
composer.phar

$ # PHP 本体(ランタイム)の保存先ディレクトリを確認
$ dirname $(which php)
/usr/bin/php

$ # PHP と同じディレクトリに拡張子なしで移動し、実行権限を与える(要 sudo 権限)
$ mv ./composer.phar $(dirname $(which php))/composer && chmod +x "$_"

$ # 動作確認
$ composer --version

composer がインストールできない環境で composer を使いたい
▼ SSH が使えないレンタルサーバーで composer を使いたい
▼ パスの通ったディレクトリにアクセス権限のないサーバーで composer を使いたい

composer は Phar 形式というだけで、実体は PHP ファイルです。つまり、$ php ./composer.phar [コマンド]$ composer [コマンド] と同等のことができます。

そのため、ローカルで composer.phar をダウンロードしてアップロードすれば利用できます。

▼ macOS の brewcomposer をインストールしたい

brew install composer

▼ シェル・スクリプトなどから composer 本体をダウンロードだけしたい

シェル・スクリプトの中身
#!/bin/sh

EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
then
    >&2 echo 'ERROR: Invalid installer signature'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT

🐒   Docker、Vagrant や CI など、スクリプトで composer をダウンロードしたい場合は上記スクリプトもしくは次項のスクリプトを利用します。このスクリプトはダウンロードのみで、環境変数の $PATH には設置(インストール)しないので注意してください。別途、任意のパスに移動させるスクリプトを追記する必要があります。
ダウンロードと同時にインストールしたい(パスを通したディレクトリに移動したい)場合は、次項も参照してください。

▼ シェル・スクリプトなどから composer 本体をダウンロード&インストールしたい

--install-dir オプションを付けるとインストール先を指定できます。また --filename オプションで保存時のファイル名を指定できます。

以下は、スクリプトでインストールすると同時に /bin ディレクトリに composer.pharcomposer としてインストールする例です。

シェル・スクリプトの中身
#!/bin/sh

EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
then
    >&2 echo 'ERROR: Invalid installer signature'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php --quiet --install-dir=/bin --filename=composer
RESULT=$?
rm composer-setup.php
exit $RESULT
  • Composer 本体のバージョンを固定したい場合は、上記の php composer-setup.php --quiet --install-dir=/bin --filename=composerphp composer-setup.php --quiet --install-dir=/bin --filename=composer --version=1.10.17 とバージョン・オプションを指定します。[composer のバージョン一覧]

▼ Docker イメージに composer 本体をダウンロード&インストールしたい

以下は php:cli-alpine の Docker イメージをベースイメージとして、composer をインストールする Dockerfile の例。

FROM php:cli-alpine

# Install composer
RUN \
    EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"; \
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"; \
    ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"; \
    [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ] && { >&2 echo 'ERROR: Invalid installer signature'; exit 1; }; \
    php composer-setup.php --quiet --install-dir=/bin --filename=composer && \
    composer --version && \
    rm composer-setup.php
  • Composer 本体のバージョンを固定したい場合は、上記の php composer-setup.php --quiet --install-dir=/bin --filename=composerphp composer-setup.php --quiet --install-dir=/bin --filename=composer --version=1.10.17 とバージョン・オプションを指定します。[composer のバージョン一覧]

composer.json

新規作成・初期化

▼ 新規パッケージ作成(自身のパッケージ作成)用に composer.json ファイルを対話式で作りたい
▼ 新規パッケージの作成を確認しながら初期化したい

$ composer init

▼ 空の composer.json ファイルを作りたい

$ composer init --quiet
  • {"require": {}} だけの composer.json が作成されます。

▼ 必要最低限の composer.json ファイルを作りたい

必須項目は "name" と "description" の2項目ですが、"license" がないとワーニングが表示されるので、実質 "name"、"description" と "license" の3項目と言えます。

$ composer init --quiet --name=my_vendor/my-package --description="My description" --license=MIT

以下の JSON ファイルが作成されます。

{
    "name": "my_vendor/my-package",
    "description": "My description",
    "license": "MIT",
    "require": {}
}
  • "name" は、以下の正規表現にマッチする必要があります。([ベンダー名]/[パッケージ名]
    • ^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$
  • "license" は、SPDX で制定されている Identifier である必要があります。

▼ 新規パッケージ作成時に、依存パッケージも指定しておきたい(ついでに require もしておきたい)
▼ パッケージの初期化時に複数の依存パッケージも指定しておきたい

$ composer init --require [vendor/package1] [vendor/package2]

require 情報だけの composer.json を作りたい

$ composer require [vendor/package1] [vendor/package2]

🐒   上記は、composer.json がない場合に require 情報だけを記載した composer.json を新規作成してパッケージをインストールしてくれます。これは、自身のパッケージは再配布予定がなく、シンプルに依存パッケージだけ使いたい場合に便利です。

require 情報だけの別の JSON ファイルを作成したい
composer.json の別名ファイルに require 情報だけ追加して作成したい

composer-other.jsonを作成する例
COMPOSER=composer-other.json composer require phpunit/phpunit

▼ 新規パッケージ作成時に、依存パッケージもバージョンで指定しておきたい

$ composer init --require vendor/package1:1.0.0

▼ 新規パッケージ作成時に、開発用のパッケージも指定しておきたい(ついでに require-dev もしておきたい)
▼ パッケージの初期化時に、複数の開発用パッケージも指定しておきたい

$ composer init --require-dev [vendor/package1] [vendor/package2]

▼ 新規パッケージ作成時に GitHub 上の自作パッケージも指定したい
▼ 新規パッケージ作成時に GitHub 上のパッケージも一緒に require しておきたい

composer init --repository '{"type":"vcs","url":"https://github.com/[YOUR]/[REPO]"}' --require [vendor]/[package]:dev-master

複製/フォーク

▼ 利用可能なリポジトリにある既存のパッケージを複製して自身のパッケージにしたい(パッケージをフォークしたい)
▼ フレームワークなどの既存のパッケージを複製して自身のパッケージにしたい(パッケージをコピーしたい)

$ composer create-project [vendor]/[package]

▼ 既存のパッケージを複製して自身のパッケージにする際にディレクトリ名を指定したい
▼ 既存パッケージをフォークする際にディレクトリ名を変えたい

$ compose create-project [vendor]/[project] [target-directory]

アーカイブ/バックアップ

▼ 依存ファイル含め、自身のパッケージをまるごと zip/tar アーカイブしたい
▼ 依存ファイル含め、指定したパッケージをまるごとアーカイブ/バックアップしたい

ZIP
$ composer archive [vendor]/[package] [version] --format=zip
TAR
$ composer archive [vendor]/[package] [version] --format=tar

パッケージのインストール

🐒   この項目は composer.json に記載済みのパッケージのインストールです。composer.json にパッケージを追加、もしくはパッケージのインストール後に新たなパッケージを追加したい場合は「追加」セクションをご覧ください。
また、インストール済みのパッケージを確認したい場合は「確認・チェック」セクションをご覧ください。

composer.json に記載されたパッケージや依存を、現在のプロジェクト(パッケージ)にインストールしたい

$ composer install

▼ PHP ベースのコマンドラインツールをどこからでも使えるようにインストールしたい
▼ パッケージをグローバル・インストールしたい

composer global require "[vendor]/[package]=[version]"
PHP-CSをグローバルにインストールしたい場合
composer global require "squizlabs/php_codesniffer=*"
  • この場合、予め ~/.composer/vendor/bin にパスを通しておく(環境変数 PATH にパスを追加しておく)必要があります。

composer.json に記載されたパッケージや依存を、現在のプロジェクト(パッケージ)にインストールする前にインストールの挙動を確認したい
▼ パッケージのインストールの事前確認をしたい

$ composer install --dry-run

composer.json に記載されたパッケージや依存をインストールする際に PHP のバージョン依存確認を一時的に無効にしたい
▼ パッケージのインストール時に PHP のバージョンを無視させたい

$ composer install --ignore-platform-reqs
  • パッケージ自身が PHP のバージョンを確認している場合、インストールできても動作しない場合があります。

composer.json の「別名ファイル」からパッケージをインストールしたい
composer.json 以外の JSON ファイルに記載されたパッケージをインストールしたい

composer-other.jsonの例(環境変数)
$ export COMPOSER=composer-other.json
$ composer install
composer-other.jsonの例(グローバル変数)
$ COMPOSER=composer-other.json composer install
  • COMPOSER 環境変数/グローバル変数に指定できるのはファイル名だけでパスの指定はできません。無効なファイル名として、デフォルトの composer.json が使われます。

▼ 依存パッケージのインストールを vendor とは違うディレクトリにインストールしたい
▼ 依存パッケージのインストール先を vendor ディレクトリとは別名のベンダ・ディレクトリにしたい
▼ ベンダーのディレクトリ名を vendor とは違うディレクトリ名にしたい
▼ composer ライブラリのインストール先を変更したい

暫定設定(hogeにディレクトリを1回のみ設定)
$ COMPOSER_VENDOR_DIR=hoge composer install
固定設定(hogeにディレクトリを固定設定する例)
$ composer config vendor-dir hoge
$
$ # 以下の要素が composer.json に追加されます
$ # "config": {
$ #     "vendor-dir": "hoge"
$ # }

▼ 依存パッケージのベンダー・バイナリを bin とは違うディレクトリにインストールしたい

ディレクトリがfugaの例
$ COMPOSER_BIN_DIR=fuga composer install

▼ 依存パッケージのインストール時にプロクシを通してインストールしたい

$ http_proxy=[URL Proxy] composer install

▼ おすすめの人気パッケージをインストールしたい
composer のパッケージを探したい

  1. Packagist の人気パッケージ一覧から探す
  2. インストールする

更新(アップデート/バージョンアップ&ダウン)

composer.json に記載されているパッケージや依存をすべて最新にしたい
▼ インストール済みのパッケージや依存をアップデート/更新したい

$ composer update

composer.json に記載されているパッケージや依存を最新にする前に挙動を確認したい
▼ パッケージをアップデートする際に事前動作の確認をしたい
▼ パッケージ・アップデートの事前確認をしたい

$ composer update --dry-run

composer.json に記載された、特定のパッケージとその依存のみを最新にしたい
▼ 特定のパッケージをアップデート/更新したい

$ composer update [vendor]/[package]

composer.json に記載された、特定のベンダーのすべてのパッケージとその依存を最新にしたい

$ composer update [vendor]/*

▼ インストール済みのパッケージで、更新可能なパッケージを知りたい
▼ インストール済みのパッケージで、パッケージが古くないかを確認したい

$ composer outdated
$ composer show -lo

▼ インストール済みのパッケージや依存をダウングレードしたい
▼ インストール済みのパッケージをバージョンダウンしたい

ダウン・グレード/バージョン・ダウンしたいバージョンをピンポイント指定します。(^などの指定はしない)

$ composer require [vendor]/[package]:1.0.0
  • 注意:上記は composer.json の指定も上書きします。

composer 本体(composer.phar)を最新のリリース版にしたい

$ composer self-update

composer 本体(composer.phar)を最新の安定バージョンにしたい

$ composer self-update --stable

composer 本体(composer.phar)を最新のプレビュー版にしたい

$ composer self-update --preview

composer 本体(composer.phar)を指定したバージョンに変更したい

v1.0.0-alpha7の例
$ composer self-update 1.0.0-alpha7

composer 本体(composer.phar)を1つ前のバージョンに戻したい
composer 本体(composer.phar)を以前のバージョンに戻したい

$ composer self-update -r
$ composer self-update --rollback

composer.json の「クラスマップの変更」を autoloader.php に反映/適用させたい
composer.json の「名前空間の割り当てマップ」の変更を autoloader.php に反映/適用させたい

$ composer dump-autoload

composer の公開鍵を更新したいDev/SnapshotTags の公開鍵)
Missing pubkey for dev verification が出るので公開鍵を更新したいcomposer diagnose 時)
Missing pubkey for tags verification が出るので公開鍵を更新したいcomposer diagnose 時)

  1. 公式の最新の公開鍵を控える
  2. 以下のコマンドで登録する
$ composer self-update --update-keys
  • ページ下部の「トラブル・シューティング」も参照のこと

追加

composer.json にパッケージを追加したい(from 利用可能なリポジトリ)

$ composer require [vendor]/[package]

composer.json にパッケージ開発時にのみ使うパッケージを追加したい(from 利用可能なリポジトリ)

$ composer require --dev [vendor]/[package]

composer.json にパッケージを対話形式で追加したい

$ composer require

composer.json に指定したバージョンのパッケージを追加したい

v2.1の例
$ composer require [vendor]/[package]:2.1

composer.json に指定したメジャー・バージョンの最新パッケージを追加したい

v1.*の例
$ composer require [vendor]/[package]:1.*

composer.json に指定したパッケージのマスターの最新版を追加したい(リリースの最新ではない)

$ composer require [vendor]/[package]:dev-master

▼ PHP のバージョンに合わせて依存パッケージのバージョンを複数指定しておきたい

例えば TravisCI で複数 PHP バージョンでテストする際の PHPUnit のバージョンなど。

$ # "||" 区切りで指定する
$ composer require phpunit/phpunit:^5.0||^4.0||^3.0

composer.json に GitHub の自分のリポジトリを追加(登録)したい

$ composer config repositories.github.com vcs https://github.com/[YOUR]/[REPO]
$ composer config repositories.github.com '{"type": "vcs", "url": "https://github.com/[YOUR]/[REPO]", "//url": "https://github.com/[YOUR]/[REPO].git"}'

**▼ composer.json に GitHub 上のパッケージを追加したい

  1. GitHub を検索対象リポジトリに追加する
  2. $ composer require [vendor]/[package]:dev-master を実行する

composer.jsonconfig キーに要素を追加したい

「bin-dir」キーに「bin/」を追加する例
$ composer config bin-dir bin/

🐒   上記を実行すると、composer.json に以下の要素が追加されます。なお、追加できるキーは composer が認識できるものに限ります。

   "config": {
       "bin-dir": "bin/"
   }

削除

composer.json の設定およびインストール済みのパッケージを削除したい

$ composer remove [vendor]/[package]

▼ 複数パッケージを一気に削除したい
▼ 削除するパッケージを複数指定したい

$ composer remove [vendor]/[package1] [vendor]/[package2]

composer のキャッシュ・ディレクトリを空にしたい(キャッシュをクリアしたい)

$ composer clear-cache

設定・修正

composer.json の設定内容を変更したい

config, repositories のキーのみ、コマンドで変更できます。

$ composer config [options] [setting-key] [setting-value1] ... [setting-valueN]

composer.json"config": { "bin-dir": "bin/" } の "bin/" を "phar/" に変えたい
composer.jsonconfig 設定を変更したい
composer.jsonconfig キーの値を変更したい

「config」項目の「bin-dir」設定を「phar/」に変える例
$ composer config bin-dir phar/

▼ 自身のパッケージに登録済みのリポジトリ情報を修正したい

$ composer config repositories.[ID] vcs https://qithub.com/[foo]/[bar]

▼ リポジトリをミラーサーバに変更したい
▼ Packagist のリポジトリを日本のミラーサーバに変更したい

$ composer config repositories.packagist composer https://packagist.jp

composer.json の設定項目を削除したい

$ composer config --unset [setting-key]

require 実行時 composer.json の登録パッケージをソートするようにしたい
composer.json"config": { "sort-packages": true } をコマンドで追加したい

 $ composer config sort-packages true

composer 実行時に PHP のバージョンを偽装したい
composer 実行時の PHP バージョンと違う、任意の PHP バージョンを指定したい

composerにあたかもPHP5.3.3で動かしているように伝える設定
$ composer config platform.php 5.3.3

上記は、各々のパッケージの composer.json に記載された require:{ "php": "<ここにバージョン>" }, に対して効果のある設定です。

しかし、パッケージ独自の実装、つまりパッケージ自身が内部でプログラム的に PHP のバージョンをチェックしている場合には効果がありません。例えば PHPUnit は自身のスクリプト内でバージョンチェックをしているため実行時にエラーが出ます。

composer が途中で強制終了するのを解除したい
composer のカスタム・ユーザー・コマンドの実行時間制限 300 秒を無効にしたい
composer が 300 秒で処理を終了してしまうのを解除したい

プロセスのタイムアウトまでの時間をゼロに設定する
$ composer config process-timeout 0
上記コマンドで、composer.jsonに以下の項目が追加されます
{
    "config": {
        "process-timeout": 0
    }
}
  • ユーザー・コマンドごとにタイムアウトを無効にしたい場合は、「その他」をご覧ください。

確認・チェック

composer 本体のバージョンを確認したい

--versionオプションでcomposerのバージョン確認する
$ composer --version
Composer version 1.9.3 2020-02-04 12:58:49

composer の基本動作を確認したいHello World パッケージをインストールして確認する)

パッケージの初期化
# rivsen/hello-world を依存パッケージとして指定
composer init --quiet --name sample/hello-world --require rivsen/hello-world:dev-master
composer install
メインのPHPスクリプトの中身
<?php
require_once "vendor/autoload.php";

$hello = new Rivsen\Demo\Hello();
echo $hello->hello(), PHP_EOL;

Hello World の確認例

$ # 検証バージョン
$ composer --version
Composer version 1.9.0 2019-08-02 20:55:32

$ # 作業ディレクトリの作成と移動
$ mkdir hello-world && cd $_

$ # composer の動作確認
$ composer diagnose
...

$ # パッケージの初期化
$ composer init --quiet --name sample/hello-world --require rivsen/hello-world:dev-master

$ # 依存パッケージのインストール
$ composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing rivsen/hello-world (dev-master 82d892b): Cloning 82d892b200 from cache
Writing lock file
Generating autoload files

$ # ディレクトリ構造の確認
$ tree
.
├── composer.json
├── composer.lock
└── vendor
    ├── autoload.php
    ├── composer
    │   ├── ClassLoader.php
    │   ├── LICENSE
    │   ├── autoload_classmap.php
    │   ├── autoload_namespaces.php
    │   ├── autoload_psr4.php
    │   ├── autoload_real.php
    │   ├── autoload_static.php
    │   └── installed.json
    └── rivsen
        └── hello-world
            ├── composer.json
            ├── readme.md
            ├── src
            │   └── Hello.php
            └── test.php

5 directories, 15 files

$ # プログラムのファイルを作成
$ touch hello-world.php

$ # プログラムを記載(好きなエディタで。以下は vim )
$ vi hello-world.php
...

$ # プログラムの内容
$ cat hello-world.php
<?php
require_once "vendor/autoload.php";

$hello = new Rivsen\Demo\Hello();
echo $hello->hello(), PHP_EOL;

$ # プログラムの実行
$ php hello-world.php
Hello World!


composer 本体が正常に動作しているか診断を行い結果を確認したい
composer 本体の動作に問題がないか確認したい

$ compose diagnose

▼ 自身のパッケージの診断を行い結果を確認したい
▼ 自身のパッケージの構文チェックをしたい
▼ 自身のパッケージの composer.json に不備がないか確認したい
composer.json の文法や構文に問題がないか確認したい

$ composer validate

composer のヘルプを確認したい

$ composer help

▼ インストール済みのパッケージ一覧を確認したい

$ composer show

composer でインストール済みのパッケージ情報を確認したい

$ composer show -i
$ composer show --installed
グローバール・インストール
$ composer global show -i
$ composer global show --installed

composer の特定のコマンドのヘルプを確認したい

$ composer help [command]

composer.json の設定内容を一覧で確認したい

$ composer config --list

composer.json が利用環境で使えるか確認したい
composer.json の依存パッケージが現在の環境で使えるか確認したい
composer.json の必要要件を満たしているか確認したい

$ composer check-platform-reqs

▼ インストール済みのパッケージをベンダーで絞りたい
▼ 特定のベンダーのパッケージがインストール済みか確認したい

$ composer show [vendor]/*

▼ 指定したインストール済みのパッケージの詳細を確認したい

$ composer show [vendor]/[package]

▼ インストール済みのパッケージでアップデートがあるか確認したい

$ composer outdated
$ composer show -lo

▼ 自身のパッケージのホームページもしくはリポジトリのサイトを表示して確認したい

$ composer home
$ composer browse

▼ すでにインストール済みのパッケージから、追加インストールのオススメを確認したい
▼ 必須ではないものの、インストール済みのパッケージが推奨する追加パッケージを確認したい

$ composer suggests

▼ すでにインストール済みのパッケージの依存関係を確認したい

$ composer depends [vendor]/[package]
$ composer why [vendor]/[package]

▼ すでにインストール済みのパッケージがどのパッケージの依存関係でインストールされたか知りたい
▼ なぜそのパッケージがインストールされているのか確認したい
▼ どのパッケージが特定のパッケージをインストールしたかを知りたい

$ composer why [vendor]/[package]

▼ インストールできなかったパッケージがなぜインストール出来なかったか確認したい
▼ パッケージのインストールで失敗した場合の理由を確認したい

$ composer prohibits [vendor]/[package]

▼ 自身のパッケージおよび依存パッケージ(追加済みパッケージ)で PHP のバージョン・アップに対応できるか確認したい

PHP8にバージョンアップ可能かの例
$ composer prohibits php:8

▼ 自身のパッケージ内のインストール済みパッケージが変更されていないか(マスターとの差分を)確認したい

$ composer status

▼ 自身のパッケージおよび依存パッケージのバージョンやライセンスを表示したい

$ composer licenses
json形式で表示
$ composer licenses --format=json

▼ インストール済みのパッケージでベンダーが提供しているバイナリ/スクリプトを確認したい

$ composer exec
$ composer exec --list

vendor/bin にあるバイナリ/スクリプトを確認したい

$ composer exec
$ composer exec --list

▼ 自身のパッケージの composer.json に記載された実行スクリプトを実行したい

$ composer run-script [script name] [args]

vendor/bin にあるバイナリ/スクリプトを実行して確認したい

$ composer exec [script name] [args]

global でインストールしたパッケージの bin ディレクトリの絶対パスを確認したい

$ composer global config bin-dir --absolute
Changed current directory to /root/.composer
/root/.composer/vendor/bin

上記の場合は /root/.composer/vendor/bin を環境変数 PATH に追加します。composerphpcs などを global インストールして、どこからでも $ phpcs 〜 と実行したい場合などに使います。


検索

▼ 利用可能なリポジトリ内のパッケージを全文検索したい
▼ インストールできるパッケージを検索したい

$ composer search [package]

▼ 利用可能なリポジトリ内のパッケージ名で検索したい
▼ パッケージ検索で、パッケージ名に絞って検索したい

ロングオプション
$ composer search --only-name [package]
ショートオプション
$ composer search -N [package]

以下は composer のコマンドではないものの、composer.json に手書きで追記したり、少しの工夫で便利に使える機能やアイデアです。


拡張/プラグイン/ユーザーコマンド/カスタム

🐒   composer のコマンドを拡張するには、大きく2通りの方法があります。拡張用のパッケージを作成してインストールする方法と、custom command と呼ばれる composer.jsonscripts 要素にコマンド名と実行コマンドを記載する方法です。

composer プラグインを作りたい

composer のプラグインもパッケージとして開発できます。composer.jsontype 属性を composer-pluginextra 属性を class に設定し、composer-plugin-api に準拠することで開発できます。

composer コマンドを拡張したい

基本的に拡張コマンド/プラグインもパッケージなので、通常のパッケージと同じ手順で拡張コマンドはインストール可能です。global オプションでインストールすると全体で利用可能になり、global オプションなしの場合は自身のプロジェクト(パッケージ)内のみで利用可能になります。手軽に拡張したい場合は、下記のユーザー・コマンドをご覧ください。

composer test で諸テストを実行できるテスト用ユーザーコマンドが欲しい

composer 自体の機能には test コマンドはありません。しかし、composer.jsonscripts 要素にコマンドを指定すると、要素のキー名でそれらコマンドを実行できるようになります。

つまり、test というカスタム・コマンドを作るということです。PHPUnit などの Unit テスト や、PHP CodeSniffer などのコーディング規約の準拠確認など、複数コマンドで自身のパッケージの品質管理をしている場合に利用できます。

例えば、これら確認用コマンド scripts 要素にコマンド名 mytest をキーにした要素を composer.json に記載すると任意のコマンド群を composer mytest だけで実行できます。

注意点として、自身のパッケージ(root パッケージ)内でしか利用できません。

mytestで実行される一連のコマンドの例
    "scripts" :{
        "mytest": [
            "php --version",
            "composer --version",
            "php vendor/squizlabs/php_codesniffer/scripts/phpcs",
            "php vendor/phpunit/phpunit/phpunit"
        ]
    }

その他/便利なTIPS

composer.jsonscripts で定義したユーザコマンドの実行時間の 300 秒制限を解除したい

PHPUnitのテストが300秒以上かかる場合の解除
{
    "scripts": {
        "test": [
            "Composer\\Config::disableProcessTimeout",
            "phpunit"
        ]
    }
}

composer bech でベンチマークを取りたい

Symfony の初期メンバーでパフォーマンス改善を担当していた dantleech 氏が公開した PHPBench を使うと、PHPUnit に近い使い心地で2つ以上のメソッド/関数/アルゴリズム間の速度の違いを測定できます。

詳細を見る

パッケージのインストール
composer require phpbench/phpbench @dev --dev
  • ベンチ・スクリプトの例
./bench/HashSampleBench.php
<?php
/**
 * @BeforeMethods({"init"})
 */
class HashSampleBench
{
    public function init()
    {
        // ダミーデータの作成
        $this->dummy = strval(\mt_rand());
    }

    public function benchHashMd5()
    {
        $val = hash('md5', $this->dummy);
    }

    public function benchHashSha256()
    {
        $val = hash('sha256', $this->dummy);
    }

    public function benchHashSha512()
    {
        $val = hash('sha512', $this->dummy);
    }
}

./bench/HashSampleBench.php にある各々のメソッドを 100 万回繰り返す composer.json の設定例。

  • Composer\\Config::disableProcessTimeout: Composer の実行制限タイムアウト時間(300 秒)を無効にする。
  • --revs=1000000: ループ回数。各々のメソッドを実行する回数。
  • --iterations=10: 反復回数。一連のベンチ(--revs)を繰り返す回数。
  • --retry-threshold=1: 許容偏差パーセンテージ/偏差間の許容エラーマージン。反復間の偏差がこの値に収まるまで反復する。
  • --report=compare: ベンチマーク(ベンチ結果)の速度比較表を出力する。
  • --report=aggregate: ベンチマークの総合レポート(速度、メモリ使用率など)を出力する。
composer.jsonの"scripts"に"bench"コマンドを追加する
{
    "require-dev": {
        "phpbench/phpbench": "@dev"
    },
    "scripts" :{
        "bench": [
            "Composer\\Config::disableProcessTimeout",
            "./vendor/bin/phpbench run --revs=1000000 --iterations=10 --retry-threshold=1 --report=compare --report=aggregate ./bench/HashSampleBench.php"
        ]
    }
}
実行サンプル
$ composer bench
> Composer\Config::disableProcessTimeout
> ./vendor/bin/phpbench run --retry-threshold=1 --revs=1000000 --iterations=10 --report=compare --report=aggregate ./bench/HashSampleBench.php
PhpBench @git_tag@. Running benchmarks.

\HashSampleBench

    benchHashMd5............................R1 I1 [μ Mo]/r: 0.373 0.373 (μs) [μSD μRSD]/r: 0.002μs 0.42%
    benchHashSha256.........................R2 I9 [μ Mo]/r: 0.676 0.675 (μs) [μSD μRSD]/r: 0.003μs 0.49%
    benchHashSha512.........................R1 I0 [μ Mo]/r: 0.860 0.862 (μs) [μSD μRSD]/r: 0.004μs 0.41%

3 subjects, 30 iterations, 3,000,000 revs, 0 rejects, 0 failures, 0 warnings
(best [mean mode] worst) = 0.372 [0.636 0.637] 0.377 (μs)
⅀T: 19.092μs μSD/r 0.003μs μRSD/r: 0.439%

+-----------------+-----------------+-----+---------+-----------------------------------------------------+
| benchmark       | subject         | set | revs    | suite:1343c44d5a2a719c55bde25711d577d5ecbe8468:mean |
+-----------------+-----------------+-----+---------+-----------------------------------------------------+
| HashSampleBench | benchHashMd5    | 0   | 1000000 | 0.373μs                                             |
| HashSampleBench | benchHashSha256 | 0   | 1000000 | 0.676μs                                             |
| HashSampleBench | benchHashSha512 | 0   | 1000000 | 0.860μs                                             |
+-----------------+-----------------+-----+---------+-----------------------------------------------------+

suite: 1343c44d5a2a719c55bde25711d577d5ecbe8468, date: 2020-05-16, stime: 06:22:00
+-----------------+-----------------+-----+---------+-----+----------+---------+---------+---------+---------+---------+--------+-------+
| benchmark       | subject         | set | revs    | its | mem_peak | best    | mean    | mode    | worst   | stdev   | rstdev | diff  |
+-----------------+-----------------+-----+---------+-----+----------+---------+---------+---------+---------+---------+--------+-------+
| HashSampleBench | benchHashMd5    | 0   | 1000000 | 10  | 420,768b | 0.372μs | 0.373μs | 0.373μs | 0.377μs | 0.002μs | 0.42%  | 1.00x |
| HashSampleBench | benchHashSha256 | 0   | 1000000 | 10  | 420,768b | 0.672μs | 0.676μs | 0.675μs | 0.683μs | 0.003μs | 0.49%  | 1.81x |
| HashSampleBench | benchHashSha512 | 0   | 1000000 | 10  | 420,768b | 0.854μs | 0.860μs | 0.862μs | 0.864μs | 0.004μs | 0.41%  | 2.30x |
+-----------------+-----------------+-----+---------+-----+----------+---------+---------+---------+---------+---------+--------+-------+


▼ 既存パッケージから新規パッケージを作る際に任意のスクリプトを実行したい
▼ 既存パッケージをクローン/フォークされた際に任意のスクリプトが実行されるようにしたい

composer create-project コマンドで自身のパッケージをテンプレート替りに使ってもらう(自身のパッケージから新規パッケージを作る)際に、任意のスクリプトを実行したい場合は、composer.jsonscripts 要素の post-create-project-cmd キーにスクリプトのパスを記載します。例えば、namespace やクラスファイル名を書き換えるなどに使えます。

create-projectコマンド実行にrename_namespace.phpを実行する例
{
    "scripts": {
        "post-create-project-cmd": [
            "php 'config/rename_namespace.php'"
        ]
    }
}

トラブルシューティング

composer が重い
composer require ... が遅い

日本国内からであれば、@Hiraku さんが建ててくださってるミラーサーバを使ってみる。

グローバルに設定する
composer config -g repositories.packagist composer https://packagist.jp

composer で定義できるライセンスの種類が知りたい
composer の "license" 項目の値一覧

composer.json で定義できるライセンス名は SPDX で制定されている Identifier のみを認識します。

license 項目が未定義の場合は、composer diagnose 時に以下のワーニングが表示されます。

license未定義時の表示
$ composer diagnose
Checking composer.json: WARNING
No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.
Checking platform settings: OK
...

例えば The Unlicense の場合は、Unlicense となります。

composer.json
{
    "license": "Unlicense"
}

SPDX で制定されていない Identifier を指定した場合は以下のメッセージが出ます。カスタム(独自)ライセンスの場合は proprietary を指定します。

license未定義時の表示
$ composer diagnose
Checking composer.json: WARNING
License "The Unlicense" is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.
If the software is closed-source, you may use "proprietary" as license.

▼ Docker のコンテナ内で composer installcomposer require すると「The "http://packagist.org/p/provider-....json" file could not be downloaded: failed to open stream: Address not available」エラーが出る。ローカルでは正常に動作する。

Docker コンテナ内の MTU とホストの MTU が合っていない可能性があります。コンテナ起動時に --network オプションで host をアタッチします。

エラーが出るパターン
docker run --rm -it -v $(pwd):/app composer:1.4.2 /bin/bash
正常なパターン(ネットワークを設定)
docker run --rm -it --network host -v $(pwd):/app composer:1.4.2 /bin/bash

composer require ... すると "minimum-stability" が合わないと言われる
... require ... -> found ... but it does not match your minimum-stability と叱られる

ルート・パッケージの composer.json で設定された安定レベル(minimum-stability)の要件と、パッケージが求める安定レベルの要件が合わないことにより、パッケージのバージョンを選択できないことによるエラーです。ルート・パッケージの composer.json で "minimum-stability" の指定がない場合、安定レベルの要件は "stable" として扱われます。

エラー表示
$ composer require ****/****

  [RuntimeException]                                                                                    
  No composer.json present in the current directory, this may be the cause of the following exception. 

  [InvalidArgumentException]                                                                                                                                             
  Could not find a version of package ****/**** matching your minimum-stability (stable). Require it with an explicit version constraint allowing its desired stability.

require [--dev] [--prefer-source] [--prefer-dist] [--fixed] [--no-progress] [--no-suggest] [--no-update] [--no-scripts] [--update-no-dev] [--update-with-dependencies] [--update-with-all-dependencies] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--] [<packages>]... 
$ composer require ****/****
[InvalidArgumentException]                                                                                                                                                                                                                     
  Could not find a matching version of package ****/****. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (stable).
  • 対応策1: パッケージのバージョンを指定する。
    • composer require ****/****:1.0.0composer require ****/****:dev-master など、
  • 対応策2: composer.jsonminimum-stability をパッケージと同じレベルに設定する。(下記 composer.json 参照)
    • 設定可能なレベル: dev, alpha, beta, RC, stable
composer.jsonに安定レベルの要件を"stable"に設定する例
{
    "minimum-stability": "stable"
}
composer.jsonに安定レベルの要件を"dev"に設定する例
{
    "minimum-stability": "dev"
}
  • グローバルにインストールしたい場合は、ユーザのホームディレクトリ(~/.composer)に移動して、require して見てください。

composer require ... すると "Token (hidden)" を聞かれる

パッケージのリポジトリからダウンロードする際に SSH 接続によるダウンロードを試みています。プライベート・リポジトリでない場合や Packagist からのダウンロードの場合、おそらく git がインストールされていません。

$ composer require ****/****
...
Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos
Head to https://github.com/settings/tokens/new?scopes=repo&description=Composer+on+docker-desktop+2020-06-27+1405
to retrieve a token. It will be stored in "/root/.composer/auth.json" for future use by Composer.
Token (hidden): 
  • 対応策: git コマンドなどパッケージ提供先のバージョン管理コマンドをインストールしてください。

composer diagnose すると "Missing pubkey for ... verification" で失敗する。composer 自体は動く。
composer self-update すると Missing pubkey エラーが出る。

$ composer diagnose
Checking composer.json: OK
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist: OK
Checking https connectivity to packagist: OK
Checking github.com rate limit: OK
Checking disk free space: OK
Checking pubkeys: FAIL                  ⇦ ここ
Missing pubkey for tags verification    ⇦ ここ
Missing pubkey for dev verification     ⇦ ここ
Run composer self-update --update-keys to set them up
Checking composer version: OK
Composer version: 1.10.8
PHP version: 7.4.7
PHP binary path: /usr/local/bin/php
OpenSSL version: OpenSSL 1.1.1d  10 Sep 2019

$ echo $?
1

これは ~/.composer/keys.dev.pub および ~/.composer/keys.tags.pub の公開鍵が存在しないことによるエラーです。

これらの公開鍵は、タグの検索や依存パッケージの検索からパッケージをダウンロードした際に(hosts ファイルの書き換えなどにより)改竄されたサイトからダウンロードされても検知出来るようにするために使われます。

  • 切り分け

    1. 実行ユーザーのホームディレクトリにある .composer ディレクトリおよび内部のファイルの所有権およびアクセス権を確認する。
  • 対応策1: $HOME/.composer ディレクトリがない場合

    • brewapt などの OS 側のパッケージマネージャーでインストールした場合、$HOME/.composer ディレクトリが作成されないことがあるのが原因。
    • 対策: 対策4と同じ
    • インストール・ユーザーと実行ユーザーが異なることにより、.composer ディレクトリが作成されなかったため公開鍵がみつからなかったことが原因。
      • 対策: インストール・ユーザーのホームディレクトリにある .composer ディレクトリを実行ユーザーのホームにコピーし、所有権とアクセス権を実行ユーザーに変更する。
  • 対応策2: $HOME/.composer ディレクトリがあるが、所有者が違う

    • インストール・ユーザーと実行ユーザーが異なっていた可能性があるので、実行ユーザーに変更する。
  • 対応策3: $HOME/.composer ディレクトリもあり、所有者も同じである

    • 以下の手順で正しい公開鍵に更新する。
    • 公開鍵を確認する: https://composer.github.io/pubkeys.html
    • 次のコマンドで DevTags の公開鍵を登録する: composer self-update --update-keys
  • 対応策4: apk apt brew と言った他のパッケージマネージャーからインストールした場合


Composer のオススメ Qiita 記事一覧


Composer の基礎知識

Composer とは

PHP における Composer とは PHP ライブラリのパッケージ・マネージャーのことです。Dockercompose とは似て非なる別のアプリです。

composer 自身も PHP で書かれており、composer.phar という phar 形式でアーカイブされた単体 PHP ファイルとして提供されています。

そのためコマンド・ラインから PHP コードを実行するのと同じように $ php ./composer.phar を指定して実行できます。

composer.phar が OS のシバンに対応していれば $ ./composer.phar のように PHP ランタイム(インタプリタ)を指定せずに実行できるため、通常はパスの通ったディレクトリに composer と拡張子を付けずにリネームして設置し、composer コマンドとして利用します。

phpランタイム・インタプリタ経由で実行(確実)
$ php ./composer.phar --help
shebang経由で実行
$ ./composer.phar --help
コマンドとして実行(推奨)
$ composer --help

$ # 設置先の例(macOS)
$ which composer
/usr/local/bin/composer

パッケージ・マネージャーとは

パッケージ・マネージャーとはパッケージの「ダウンロード」「更新」「削除」「共有」「利用」を手助けしてくれるツールです。一般的にコマンドで実行して利用します。

パッケージとは、自身もしくは他者が開発したプロジェクト/ライブラリ/ツール/プログラム/etc. をセットとして提供できるように1つにまとめ・・・たものです。パッケージマネージャーは、その「パッケージの管理を補佐するためのツール」です。

例えば、Python における pip、Anaconda における conda、Ruby における gem、Node.js における npmyarn、Debian における apt、CentOS における yum、Alpine における apk、Mac/Linux における brew、Windows における chocowinget などのように、PHP にもパッケージを管理するコマンド・ツールがあります。

従来からある PECLPEAR に加えて、本記事の composer です。他にも、依存ファイルも含めて Phar で固めた(アーカイブされた)パッケージを管理する Phive もあります。

PEAR は永らく PHP の主要なパッケージマネージャーとして君臨していました。しかし PEAR は「お役御免」となり、現在は composer が主要なパッケージマネージャーであると言えます。特に composer の v1 系では pear の代替コマンドがあったのですが、新しい composer の v2 からは pear も使えなくなりました。最近の書籍でも PEAR でのインストールを案内するものがありますが、同じものがあるなら composer でインストールすることをお勧めします。

対して PECL は(まだ?)現役です。なぜならコンパイル済みのバイナリ、つまり PHP の Extension(拡張機能)を扱うことが出来るからです。

PHP の composer の場合は、位置付け的に Python の pip や Node.js の npm が一番近いかもしれません。対して PHP の PECL は、Python の Anaconda との関係に近いと思います。Mac ユーザーであれば composerPECL の関係は brewbrew cask の関係みたいなものと言えばピンと来るでしょうか。

と言うのも、PHP の composer や Python の pip は基本的に自身のプログラム言語で書かれたパッケージを管理するのに対し、PHP の PECL や Python の Anaconda は、それ以外にも C 言語と言ったコンパイル型言語で書かれた外部モジュール(言語を拡張する機能)も取り扱え、必要であればソースコードからコンパイルを行うこともできます。

しかし、PHP も PHP 7.4 から FFI と言う「多言語で書かれたライブラリを使う仕様・機能」が使えたり、PHP 8 からは JIT と言う「 実行時にコードのコンパイルを行い実行速度の向上を図る機能」も使えたりと、プリ・コンパイル言語になりつつあるので PECL もいずれ消えていく可能性は高いと思われます。

パッケージ・マネージャーの目的

パッケージ・マネージャーの主な目的は「車輪の再発明防止」です。

つまり、既存のパッケージを再利用することで DRY の原則を支援するツールでもあります。車輪を再発明して大車輪を作る場合を除き、既存のパッケージを利用することで工数削減が期待できます。また、公開してシェアすることで多数の目を通すことになるため、改善やセキュリティ対策などのメンテナンスの気付きを得られるという目的もあります。

パッケージ・マネージャーの特徴

パッケージ・マネージャーの基本となる特徴として「依存関係の管理」があります。

つまり、「パッケージ A を使うためには、パッケージ B のバージョン X が必要だが、パッケージ B はパッケージ C のバージョン Y が必要」といった場合に、必要なメインのパッケージ A を宣言するだけで、芋づる式に必要な(関係する)他のパッケージも管理してくれます。

パッケージの管理

composer のパッケージの管理は、基本情報を記載した composer.json ファイルと composer コマンドで管理します

composer コマンドは composer.json を参照して処理を行います。そのため、composer.json ファイルと同じ階層、もしくはオプションでファイルのパスを指定して composer コマンドを実行することで管理します。

一般的に、自身のプロジェクト(プログラム)のルート・ディレクトリcomposer.json 設置しますが、composer では、そのディレクトリを「root パッケージ」と呼びます。

composer.json ファイルがプロジェクトにまだない場合は composer init で初期化するか、composer require で依存パッケージを追加するか、手動で設置します。

もし、自身のプロジェクトで特定のパッケージを使うことがわかっている場合は composer require <パッケージ名> と実行して composer.json に追記 & パッケージのインストールをします。

この時 composer.json が存在しない場合は作成してから追記とインストールをしてくれるので、再配布する予定がない場合は init より requireらくでしょう。

逆に、すでに記述済みの composer.json がある場合、composer install で依存するパッケージのインストール(vendor ディレクトリにダウンロード)が行えます。

ダウンロードまでの大まかな流れですが、composer require もしくは composer install が実行されると、composer.json に記載されている依存パッケージの各々の composer.json をローカル(~/.composer/cache)に一旦ダウンロードします。

次に、それらの compose.json から依存関係を計算したのち、必要にあわせてパッケージの本体を vendor/ ディレクトリ下にダウンロードして行きます。

Composer では自分のプロジェクトもパッケージ

このように、自身のプロジェクトのルート・ディレクトリにある composer.json は、自分のプロジェクトの依存関係を記載したファイルです。

同様に、自身のプロジェクトだけでなく依存するパッケージの各々のルート・ディレクトリにも composer.json が設置されるのが composer の特徴です。Python でいう __init__.py や Golang でいう go.mod に近い役割をするものです。

composer では、この composer.json ファイルがあるディレクトリ以下を「パッケージ」と呼び、1つの単位とします。そして、自分のプロジェクトを「ルート・パッケージ」と呼びます。つまり、これが composer において、自分のアプリも「パッケージ」と呼ぶゆえんです。

この仕組みにより、自分のプログラムが他のプログラムからでもパッケージとして気軽に使えます。

また、依存するプログラムも一緒に配布しなくても済むため、開発用の配布データのサイズが小さくなるというメリットもあります。特に、ライセンス上の問題で自身のパッケージと一緒に配布できない場合にも効力を発揮します。

パッケージの種類

composer のパッケージには主に4つの種類(type)があり、パッケージの用途によって異なります。

composer.json の "type" 設定項目(JSON の要素)でパッケージの用途を示すことができ、下記の4種類から選べます。

  1. library(ライブラリ):
    デフォルトの設定値。ライブラリ用途で使うパッケージの場合に指定します。ライブラリとは、使いやすいように1ヶ所に整理してまとめられたもので、特定の目的に合わせて選抜された関数やクラスなどまとめたパッケージを指します。他の言語でいう .dll.so のような位置付けのパッケージです。
  2. project(プロジェクト):
    ライブラリではなく、それ自体がアプリケーションとして動作するパッケージを示します。たとえば、Symfony SE のようなアプリケーション・シェル、SilverStripe インストーラーのような CMS、またはパッケージとして配布される本格的なアプリケーションなどです。IDE によっては、新しいワークスペースを作成するときに、この値を利用して初期化するプロジェクトのリストを提供するものもあります。
  3. metapackage(メタ・パッケージ):
    要件のみを定義した空のパッケージの場合に指定します。パッケージ自体はファイルを含まないため、composer install で実行してもファイルシステムに何も書き込みませんが、記載されたパッケージのみをインストールします。主に、開発前の定番のパッケージをインストールする用途に使われます。
  4. composer-plugin
    composer の拡張機能用のパッケージである場合に指定します。vendor ディレクトリ以下にインストールしないカスタム・インストーラーを実装する必要があります。

上記4つ以外にもユーザー定義の値を指定することができます。その場合 symfony-bundlewordpress-plugin などのように、特定のプロジェクト用の固有パッケージであることを意味し、カスタム・インストーラーなどから利用されます。

以上から、通常は library として使うことが多く、次点として project が多く使われます。

composer.lock とは

composer.lock とは「ダウンロードされたパッケージの諸情報」が記載されているファイルです。別の言い方をすると「動作確認された時のバージョン情報ファイル」です。Golang の場合は go.sum に相当するものです。

composer.lockcomposer.json と同じ階層に作成され、composer コマンドを実行すると作成・更新されます。

composer.json は自身のパッケージの情報、composer.lock はダウンロードされたパッケージの情報と覚えるといいでしょう。「自身のパッケージが動作した」と確認が取れた場合、その時点の各々のパッケージのバージョン情報などが記載されるため、パッケージの動作保証ファイルとも言えます。

composer.lock の注意点

一般的に composer.lock はユーザーに提供しません。しかし、composer.lockcomposer.json と一緒に配布する場合があるので注意します。

と言うのも、自身のパッケージや依存するパッケージの各々の composer.json ファイルではバージョンが決め打ちされていないことが多くあります。例えば「バージョン 1.0 以上」の意味である「^1.0」などと設定されてる場合です。その場合、composer は依存関係を見ながら可能な範囲で一番最新のバージョンを使おうとします。(バージョンの詳細は次項)

つまり、「ある時点」もしくは「ある環境」では動いたはずなのに、別のタイミングや環境で動かそうとすると、パッケージの最新バージョンが異なるため動かなくなる場合が出てくるということです。その可能性がある場合は、composer.lock も共有します。

使い方は composer.jsoncomposer.lock を同階層に設置した状態で $ composer install もしくは $ composer update します。すると、動作確認の取れたバージョンの依存パッケージがダウンロードされます。

composer.lock を提供する際の注意点もあります。それは、全てのパッケージのバージョンが composer.lock で決め打ちになることです。

つまり、セキュリティ・アップデートなどが適用されないバージョンになる可能性があると言うことです。

そのため、一般公開するパッケージには composer.lock は共有しません。テスト環境から本番環境への移行や Docker のコンテナといった「デプロイ先の環境の均質度が高い」場合、つまり利用する環境が明確な場合や、「動かない」と言った場合などに提供します。

更新を忘れない自信がある場合は composer.lock.debug などとリネームして提供してもいいでしょう。

各々のパッケージのバージョンを「決め打ちする」と安定性は増しますが、メンテナンス(バージョンの追随)頻度が高くなります。

逆に、バージョンを「常に最新にする」と競合する頻度が高くなります。これは依存する複数のパッケージがとある 1 つのパッケージを参照するも、アップデートによるパッケージの仕様変更に依存元が追随できていない場合などです。

どちらが良い・悪いではなく、運用ポリシーや人件費との問題で、どのパッケージ・マネージャーも持っているジレンマと言えます。

開発手法の1つである「テスト駆動開発」は、このジレンマを軽減することができます。ユニット・テストおよび CI の導入によって、「古いバージョンおよび最新のバージョンでも問題なく動くか」の確認が容易になるからです。

Composer パッケージのバージョン指定の種類

composer のバージョン検知はセマンティック・バージョニングの記法に準拠しています。

つまり、1.10.3 のような X.Y.Z と3つの区切りで分けられ、各々<メジャー>.<マイナー>.<パッチ> と3つのバージョンをドット区切りで示しています。1.2 のようなパッチ・バージョンが指定されていない場合は、内部で 1.2.0 もしくは 1.2.x の最大値といった補完を行います。

そのため、自身のパッケージのバージョンを変更する場合のルールも、セマンティック・バージョニングに準拠する事が推奨されています。

前述したように、composer のバージョン指定には大きく「静的指定」と「動的指定」の2種類があります。

静的指定は、いわゆる「バージョンの決め打ち」で、^ ~ - と言った記号を使わないバージョン指定です。1.2.3 のように指定し、常にそのバージョンが使われるように指定するタイプです。

逆に動的指定は、記号を使うことで使用するバージョンに条件を付ける事ができます。

  • バージョン範囲: >, >=, <, <=, !=, -, ~, *, ^
  • AND 指定: スペースもしくは ,
  • OR 指定: ||
記号 概要 指定例 最小バージョン 最大バージョン
- 範囲指定 1.0 - 2.0 >=1.0.0 <2.1
- 1.0.0 - 2.1.0 >=1.0.0 <=2.1.0
.* ドット付きワイルドカード 1.0.* >=1.0.0 <1.1
* ワイルドカード
(必須だがバージョンは問わない)
* 問わない 問わない
~ 最新パッチバージョン ~1.2 >=1.2.0 <2.0.0
~ ~1.2.0 >=1.2.0 <1.3.0
~ ~1.2.3 >=1.2.3 <1.3.0
^ 最新マイナーバージョン ^1.2.3 >=1.2.3 <2.0.0
^ ^0.3 >=0.3.0 <0.4.0

パッケージのダウンロード元

composer の場合、パッケージのダウンロードは指定されたリポジトリから行われます

デフォルトでは、composer の有志のコミュニティが管理している "Packagist" のリポジトリが検索対象になっています。

この Packagist に登録されたパッケージは、リポジトリの追加なく「vendor/package」(作者名/パッケージ名)を指定するだけで使えるようになっています。Python の pip で言うところの PyPI(Python Package Index)です。

プライベートなパッケージ、つまり Packagist で一般公開していないパッケージも利用できます。

例えば GitHubローカルで立てた Git サーバといった、アクセス可能な VCS リポジトリで公開しているパッケージだったり、PackagistGitHub などの有料オプションでプライベート・リポジトリを契約して利用するなどです。

macOS の brew で言うところの tap に近い仕組みですが、任意のリポジトリを検索対象に追加することで利用可能になります。

現在対応しているリポジトリの種類は Git/SVN/Hg です。(詳しくは下記「自作パッケージの公開方法」参照)

パッケージのダウンロード先/インストール先

インストールしたパッケージの保存先は global オプションを「付けた場合」と「付けない場合」で異なります

  • global オプション「あり」 ... 同じユーザーの全プロジェクトで利用可能なパッケージとしてインストール
  • global オプション「なし」 ... そのプロジェクトでのみ利用可能なパッケージとしてインストール

global オプション「あり」でインストールした場合は、現在のユーザーのホーム直下の ~/.composer/vendor/ ディレクトリにインストールされます。

global オプション「なし」でインストールした場合は、composer.json のあるカレント・ディレクトリ直下の ./vendor/ ディレクトリにインストールされます。

いずれのインストール方法にしても、パッケージをインストールすると vendor ディレクトリ下に保存されると覚えておいてください。

ダウンロード/インストールされるパッケージの種類

composer には、パッケージをダウンロード/インストールする際、2種類のパッケージがあります

「プロジェクト本体が使う」パッケージと「プロジェクトの開発に使う」パッケージです。つまり、オーペレーション(Ops)用とデベロップメント(Dev)用です。

Ops 星人用パッケージ

オペレーション(運用/実行)に必要なパッケージとは「プロジェクト本体(自分のアプリ)を動かす際に必要なパッケージ」です。

例えば、作りためていた汎用の俺様クラスや俺様関数があった場合、別のパッケージとしてリポジトリに用意しておき再利用する場合です。それ以外にも、他の先人方が開発・共有してくださってるパッケージを利用する場合などです。これらのパッケージの力を借りて実装します。

具体例としては、PHP でコマンド・ライン・ツールを作りたい場合、Pure PHP と制御コードを駆使してゼロから開発してもいいのですが、スキルと経験がつくなど勉強にはなるものの、時間がかかります。

そこで既存のパッケージの利用を検討します。この場合、老舗の Web のフレーム・ワークの1つである Symfony が、その機能をコンポーネント化して symfony/console パッケージとして提供しているので、以下のコマンドでパッケージを導入します。

プログラム本体用に使うパッケージを指定する例
composer require symfony/console

Dev 専パッケージ

対して、デベロップメント(開発)に必要なパッケージとは「プロジェクト本体(自分のアプリ)を動かす際に必要のないパッケージだが、入れておくと開発が捗るパッケージ」です。

例えば、ユニット・テスト、コーディング規約のチェック、静的解析、脆弱性のチェックやベンチマークといった開発やメンテナンスに必要なパッケージを指します。

Dev 専用として使いたい場合は composer require する際に --dev オプションを付けてパッケージを指定します。

例えば自分のプロジェクトにユニット・テストを取り入れたい場合、有名どころでは PHPUnitphpunit/phpunit パッケージがあるので --dev を付けて指定します。

プログラム本体の開発に使うパッケージを指定する例
composer require --dev phpunit/phpunit

--dev オプションをつけると composer.json 内の require-dev 要素に追加されます。上記の例の場合は、バージョンの指定がないため、composer が自動的に現在の PHP バージョンに合わせて必要なバージョンの記載もしてくれます。

Ops 専用インストール

実際の利用、つまりエンドユーザー(利用者)には基本的に開発用パッケージは必要ありません。開発のフレームワークによってはサイズが大きいものもあり、空き容量を無駄に消費することになります。

その場合、利用先で composer install する際に --no-dev オプションを付けることで、dev 系のパッケージはインストールされないのでダイエットできます。

プログラム本体に必要なパッケージのみをインストールする
composer install --no-dev

パッケージの実行方法/パッケージの利用方法

インストールしたパッケージの実行/利用には大きく2種類の方法があります。「インポートして利用する」か「直接実行する」かです。

「インポートして利用する」場合は、後述する autoload の仕組みにより自身のパッケージ内でライブラリとして呼び出して利用します。つまりパッケージを require して利用する場合は、一般的に global オプション「なし」でインストールします。

「直接実行する」場合は、一般的に global オプション「あり」でインストールし、~/.composer/vendor/bin/ ディレクトリにパスを通してコマンドとして利用します。

bin ディレクトリとは言っても必ずしもコンパイルされたバイナリデータの置き場所というわけではなく、「単体で実行可能なファイル」を置きます。例えばシェバン付きの PHP ファイルです。

具体的な例として、コーディングやスタイルの規約に準拠しているか判定する「PHP CodeSniffer」をインストールすると vendor/squizlabs にライブラリが、vendor/bin/phpcs コマンドが設置されます。

この vendor/bin/phpcs は拡張子のないシェバン付きの単体 PHP ファイルです。標準入力を受け取るように組んであるため、シェルからコマンドとして利用できるようになっています。

試しに適当な空のディレクトリを作成し、そのなかでシェルから global オプション「なし」で composer require squizlabs/php_codesniffer と実行してインストールしてみてください。ディレクトリ構造を確認してみるとパッケージ作りの参考になると思います。

しかし、全てのパッケージが vendor/bin にコマンドを設置するわけではありません

それでも、もしパッケージが bin ディレクトリにコマンドを設置するタイプであった場合は、ターミナルから $ ./vendor/bin/phpcs --version と、コマンドとして実行できます。

そのため、プログラム内でなく汎用的に使いたいパッケージの場合は「global オプションあり」でインストールし ~/.composer/vendor/bin/ にパスを通しておくと $ phpcs --help とどこからでも使えるようになります。

もちろん「global オプションなし」でインストールし、アプリ内から相対パスで ../../bin/ とディレクトリを参照し、外部コマンドとして実行することも可能です。また、ライブラリとして対応していれば、後述する autoload の仕組みでインポート、つまり include したのと同じように、そのライブラリのクラスや関数が使えるようになります。

自身のパッケージで bin のファイルを提供する

composer は、各々のパッケージで bin を見つけると(composer.jsonbin の設定を見つけると)、./vendor/bin ディレクトリに各々のエイリアスを貼ったファイルを作成します。

そのため、自身のパッケージがコマンドなど単体として利用可能なものであった場合、bin ディレクトリにメインのプログラムを置いておくとユーザーは使いやすくなります。

設置する方法は主に以下の3通りがあります。

  1. BOX3 などのアーカイバーを使って phar アーカイブを作成して設置する。
  2. メイン・スクリプトを相対パスで参照するスクリプトを設置する。
    (メイン・スクリプトのシンボリック・リンクを置いても動きますが、OS に依存するためオススメしません)
  3. 全てを内包した PHP ファイルを設置する。

いずれの場合も composer.jsonbin 要素にスクリプトのパスを記載しておく必要があります。

composer.json
{
    "bin": ["bin/my-script", "bin/my-other-script"]
}

Composer の特徴とメリット 〜オートローダー〜

composer ならではの特徴とメリットとして「autoloading を標準で備えている」があります。

これはパッケージの管理だけでなく「ライブラリとしての利用を便利にする機能」で、一言で言うと「クラスや関数を小分けにしているのに requireinclude が減らせる」ことです。

ここで言う「ライブラリ」とは、再利用やメンテナンスしやすいように、特定のディレクトリにクラスや関数などを個別のファイルにわけたものです。そして利用時に requireinclude などでインポートして利用するものを言います。つまり composer でインストールしたパッケージもライブラリの1種なのです。

通常、これら外部ファイルを使う場合は毎回 requireinclude しないといけません。しかし、autoload の機能を使うと自動的に読み込んでくれるのです。

この仕組みを「オートローダー」と呼び、自分で実装することも可能です。composer のありがたみを知るためにも、以下の記事を一読されることをおすすめします。

オートローダーの基本

composer のオートローダーを使うには、パッケージをインストールすると自動作成される vendor/autoload.php のファイルを require_once することで使えます。

つまり、自分のプログラム内で1度だけ require_once('vendor/autoload.php'); と記述することでパッケージやライブラリが呼び出されます。(もちろん require 出なく include でも動きます)

逆に言えば composer のパッケージを使うには、この記述は必須とも言えます。

./src/index.php
<?php

require_once("../vendor/autoload.php");

さて、composer でインストールしたパッケージ以外にも、自作ライブラリ用のディレクトリを作成し composer.json にパスを記載しておくと自動読み込みさせることができます。つまり、以降はファイルを増やすたびに requireinclude する手間が省けるようになります。

問題は、このパスを記載するためのコマンドがないことです。

そのため、「手動で composer.json に記載しないといけない」ので、いささか初心者には敷居が高くなりますが、強力で便利な機能なので知っておいて損はありません。

オートロードの種類

自身のパッケージ内に置いた自作ライブラリをオートロードの対象にするには、composer.jsonautoload 要素に「オートロードの種類」と「パス」を記述する必要があります。

「オートロードの種類」には、"files"、"psr-4"、"psr-0" と "classmap" の合計4つが指定できます。いずれも vendor/autoload.php を読み込むと発動するものです。

  1. files
    この項目に記載されているファイルを全て include します。
  2. psr-4
    PSR-4 に準拠したクラス・ファイルを読み込みます。具体的には、この項目に記載されている名前空間と検索ディレクトリを紐付けて use で指定すると include されます。(PSR については後述)
  3. psr-0
    PSR-0 に準拠したクラス・ファイルを読み込みます。現在は非推奨となっています。具体的には、名前空間とディレクトリを同じにして use で指定すると include されます。
  4. classmap
    指定されたディレクトリにあるファイルを検索して、クラス名とファイルのパスの対応表が作成されます。クラスが利用された際、それが未定義の場合に対応表を参照し include される遅延読み込み型です。主に PSR-4 もしくは PSR-0 に準拠していないクラス・ファイルを使いたい場合に利用します。
オートロードの書き方

いくつか例を上げますが、以下の記事もご覧ください。

以下は、「オートロードの種類」に files を指定する例です。

composer.json
{
    "autoload": {
        "files": [
            "src/MyConstants.php",
            "src/MyLibrary/Myfunctions.php",
            "lib/network/MyClassess.php"
        ]
    }
}

上記は、vendor/autoload.php のファイルを1回読み込むだけで、記述されているファイルを全て include してメモリに読み込みます。

便利な反面、注意すべき点があります。

  1. 全てをメモリに読み込むため速いが、使わなかったとしてもメモリを食う。
  2. ソースコードを見ただけでは、これらが読み込まれていることが把握しづらい(確認事項が増える)。
  3. ファイルを追加するたび、composer dump-autoload コマンドを実行して vendor/autoload.php を更新する必要がある。

上記は、プロジェクトが大きくなると開発のボトルネックになりうるため、さらに2種類の方法があります。use で宣言して読み込む方法と、クラスが利用された時に宣言されていない場合に検索して読み込む方法です。いずれもクラスの利用に特化しているので、関数をオートロードしたい場合は、クラス化してメソッドにするか、files で読み込む必要があります。

PSR-4 のオートロードの例

PHP には PHP-FIG と言う団体による PSR と言う規格があります。このうち PSR-0 と PSR-4 がオートローダーの規格です。PSR-0 は非推奨となっているので、ここでは PSR-4 を例にします。

composer.json
{
    "autoload": {
        "psr-4": {
            "MyVendorName\\MyPackageName\\": "src/class/"
        }
    }
}

上記設定の場合は、ソースコードに use MyVendorName\MyPackageName\Hoge; と記述すると、src/class/ ディレクトリにある Hoge.php を読み込み、そこに記載されているHoge クラスがコード内で使えるようになります。

「え?毎回 include()require() するのと変わらないじゃん...」と思うかもしれません。

これに関してはそうです。

しかし、include() などの場合はファイルのパスを指定するのに対し、PSR のオートローダーは名前空間から読み込むファイルを指定します。これにより、複数ライブラリがあった場合に、設置先を気にせず、どんなライブラリが使われているかの把握がしやすくなります。

また、中間的なタイプとして、名前空間とディレクトリ構成を同じにした PSR-0 もあります。しかし、柔軟性に乏しいなどメリットよりデメリットの方が多いことから、現在は非推奨となっています。

自作パッケージの公開方法

自作パッケージの公開には、主に2種類の方法がありますPackagist で公開するか、それ以外です。

1つは Packagist に公開して composer require してもらう方法です。もっとも一般的であり、関係者以外にも利用してもらいたいパッケージの場合に利用します。関係者のみ、つまり Packagist で非公開利用したい場合は、有償の Private Packagist も利用可能です。

もう1つは、GitHub などの VCS リポジトリ・サービスや、ローカルで立てた Git サーバなどにパッケージを公開する方法です。その場合は、利用者にそのリポジトリを検索先として追加してもらい require してもらう必要があります。非公開のリポジトリの場合はログイン情報なども必要になります。

いずれの方法でも、リポジトリのルートに composer.json が設置されており、最低限の項目(name description必須情報)を記載しておく必要があります。

自作パッケージを Packagist で公開する

自作パッケージを Packagist で公開するには、Packagist にアカウントを作成し、リポジトリの URL を登録します

具体的には、Packagist にログインして "[submit]" からパッケージを登録できます。この時、パッケージそのものを指定(アップロード)するのではなく、外部 VCS リポジトリを指定します。対応している VCS は Git/SVN/Hg です。

例えば、GitHub にパッケージを公開し、リポジトリの URL(末尾に.git が付いたもの)を Packagist の "submit" から登録をすると、問題がない場合は Packagist でパッケージが公開されます。

🐒   Packagist での公開例: GitHub のリポジトリ と、それを紐づけた Packagist のリポジトリ

235
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
KEINOS
A Japanese made in Mexico with Mexican quality ;-) Who monkey around the jungle of codes. 記事の日本語がおかしかったら遠慮なく編集リクください。また、記事に「LGTM」が付くたび、やる気に比例して見直して何かしら加筆・修正してブラッシュアップしています。基本的に変更通知はお送りしません。
qiitadon
Qiitadon(β)から生まれた Qiita ユーザー・コミュニティです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
235
Help us understand the problem. What is going on with this article?