目次


一新された PHP

Composer による PHP 依存関係の処理

強力なオープンソース・ツールを使って PHP プロジェクトをサード・パーティー・ライブラリーからアセンブルする

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: 一新された PHP

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:一新された PHP

このシリーズの続きに乞うご期待。

PHP が成熟するにつれ、PHP で作成するアプリケーションの複雑さが劇的に増してきました。最近の PHP 開発者は、ほとんどの場合、ソフトウェア・プロジェクトの開発時間を短縮するためにサード・パーティー・ライブラリーを利用しています。例えば、Facebook 規模のアプリケーションともなると、現在 PHP で利用できる十分に管理されたサード・パーティー・ライブラリーを使用せずに作成するのは不可能です。しかしソフトウェアの再利用には、メリットがある一方でデメリットもあります。アプリケーションのインストールごとに必要なライブラリーのリストを管理しなければならないだけでなく、依存関係のツリーも管理しなければなりません。依存関係のツリーは、それぞれのライブラリーが互いに依存していることから作成されます。複雑に入り組んだ、複数のライブラリーの相互依存関係を管理するには、どうすればよいでしょう?

これまで PHP 開発者が一般に使用してきた依存関係処理ソリューションは 2 つあります。いずれも今では有効なソリューションではありませんが、そのうちの 1 つは、必要なすべてのライブラリーを、アプリケーション・コードと一緒にバージョン管理リポジトリーにチェックインするというソリューションです。この手法はある程度までは功を奏しますが、逆に問題の原因となることも珍しくありません。ライブラリーの独自のローカル・バージョンを保守しなければならないためです。したがって、ライブラリーの新しいバージョンをダウンロードしてリポジトリーにチェックインするという方法で、ライブラリーに有効なあらゆるバグ・フィックスを手作業で実装しなければなりません。そのため最終的には、バージョン管理リポジトリーが実際のコードにはまったく関係のない大量の変更ログで溢れかえることになります。このような理由から、ライブラリーは一般に、最初にチェックインされたときのバージョンのままにされ、更新されることはめったにありませんでした。

この問題を解決することを 1 つの目的として設計されたのが、PEAR (PHP Extension and Application Repository) プロジェクトです。PEAR は、一連の連動するライブラリー (プログラマーは、これらのライブラリーにコントリビュートすることができます) を提供します。PEAR にはさらに、ライブラリーを (依存関係が存在する場合は) その依存関係と一緒にインストールするためのコマンド・ライン・ツールも組み込まれています。PEAR は問題解決のための最善のアプローチとして、多くの開発者に長い間使用されていましたが、このシステムにも欠点があります。

その欠点とは、PEAR ライブラリーのインストールはオペレーティング・システム上でグローバルに保管されることです。この設計により、ライブラリーを独自のバージョン管理リポジトリーにチェックインする必要はなくなりますが、解決される問題よりも引き起こされる問題の方が多くなります。それは、使用するシステム上で実行されているライブラリーのバージョンがわからないからです。こうしたことによる混同が、バグと勘違いしてしまう原因になることは珍しくありませんでした。つまり、アプリケーションを新しいサーバーにインストールした後、アプリケーションが機能しない理由について行き詰まった末、最終的に問題のサーバーに正しい PEAR ライブラリーが置かれていないことに気付くといった具合です。さらに、これらのグローバル・ライブラリーをインストールする権限も必要でした (これは、共有ホスティングで多くの人が悩まされていた問題です)。

誰もが知っているように、デバッグの難しさは、最初にプログラムを作成するときの 2 倍にも及びます。プログラムを作成するときに持てる限りの知恵を絞ったとしたら、いったいどうやってデバッグすればよいのでしょう?

Brian Kernighan

2011年 4月に、Nils Adermann と Jordi Boggiano という 2 人の PHP 開発者が、PHP では依存関係処理の問題に新しいソリューションが必要だと考え、その取り組みを開始しました。その結果、彼らが 2012年 3月 1日にリリースしたのが、Composer です。Composer では、開発者はアプリケーションに必要なサード・パーティー・ライブラリーを (どこでホストされているかに関わらず) 指定する構成ファイルを作成します。その上で Composer を実行すると、完全なアプリケーションが compose (作成) されます。指定されたライブラリーとその依存関係のすべてを Composer がダウンロードしてくれるからです。この記事では、Composer の基本事項をひととおり取り上げ、このツールを PHP プロジェクトで使い始める方法を紹介します。

Composer をインストールする

Composer はマルチプラットフォーム・ツールです。UNIX ベースのコンピューターや Linux コンピューターには、簡単にインストールすることができます。ローカルにインストールするには、curl でインストーラーを取得して PHP で直接実行します。

curl -sS https://getcomposer.org/installer | php

上記のコマンドにより、ローカルの composer.phar 実行ファイルに Composer のインストールが作成されます。このインストールをシステム上のどこからでもグローバルにアクセスできるようにするには、composer.phar をパスのディレクトリーにコピーします。以下に一例を示します (ルート・ディレクトリーに対する書き込み権限を得るために、sudo を使用しなければならない場合があります)。

mv composer.phar /usr/local/bin/composer

これで、システムの任意の場所で、コマンド・ラインから composer を実行することができます。

Windows の場合、手作業でインストールするのは少し難しいので、Composer の作成者たちがインストーラーを開発しました。そのインストーラーは、ダウンロードして実行することができます。インストールが完了したら、Windows コマンド・ラインから Composer を使用することができます。

基本的な使用法

Composer は、驚くほどの数のオプションを揃えた強力なツールですが、最も一般的な Composer の使用法は、サード・パーティーが提供する構成に基づいて、サード・パーティーの PHP アプリケーションまたはフレームワークのコード・ベースを作成/ダウンロード/インストールする、というものです。例えば、Zend Framework とその依存関係のすべてをインストールするために Composer を使用することができます。install コマンドで Composer を実行するだけで、後は Composer が引き受けてくれます。

Composer をグローバルに (または Windows に) インストールした場合は、以下のコマンドを実行します。

composer install

1 つのアプリケーション用にだけ Composer をローカル・インストールした場合は、以下のコマンドを実行します。

php composer.phar install

この記事で以降に記載する例では、Composer がグローバルにインストールされていることを前提とします。

Composer はプロジェクト/アプリケーションに必要なすべてのライブラリーをダウンロードするだけでなく、開発者がそのすべてのライブラリーを簡単に組み込むための手段も用意しています。Composer は vendor という名前のフォルダーにすべてのライブラリーをインストールすることで、それらのライブラリーをユーザー自身のプロジェクトのコードとは区別します。vender フォルダー内には、autoload.php という名前のファイルが作成されます。このファイルをプロジェクトに組み込むことで、Composer によって自動的にダウンロードされたすべてのライブラリーのオートローダーがセットアップされます。

require 'vendor/autoload.php';

Composer がライブラリーを見つける方法

自動的にライブラリー・パッケージをダウンロードするには、まず始めに、該当するパッケージをどこで探せばよいかを Composer に認識させる必要があります。この情報を提供するのが、Composer リポジトリーです。Composer リポジトリーは、インターネットで入手できるパッケージ、各パッケージの取得方法、そしてパッケージ自体の依存関係をリストにしたオンライン・ソースです。開発者自身が内部ライブラリーにアクセスできるように独自のリポジトリーを保守することもできますが (その方法は、Composer Web サイトで説明しています)、メインのリポジトリーとして使用することになるのは、Packagist です。Packagist では、PHP のオープンソース・プロジェクトの大部分のパッケージを提供しています。Packagist にアクセスすれば、必要なライブラリーを見つけることができます。

うまく連動することで知られているソフトウェア・ライブラリーはそうそうありませんが、Packagist ライブラリーのすべてを結び付けるものが、php[tek] 2009 カンファレンスで発足した PHP FIG (Framework Interop Group。旧称 PHP Standards Group) によって提供されています。よく使われている数々の PHP アプリケーションおよびフレームワークを提供している個人またはグループの代表者からなる PHP-FIG は、それぞれの PHP プロジェクトがうまく連動するかどうかを確認するために編成されたグループです。この協力作業の集大成として、ライブラリーのオプションの標準を記述した PSR (PHP Standards Recommendations) が作成されました。これらの共通の標準を実装するライブラリーは、共有されている一連の要求事項の下で相互運用することができます。

Composer の作成を促進した最も重要な PSR は、PSR-0PSR-4 です。この 2 つの PSR は、クラスと名前空間の共通命名規則、そしてクラスと名前空間をファイル・システム上のファイルにどのようにマッピングするか、をそれぞれ宣言しています。これにより、共通オートローダー・インターフェースは、どのライブラリーからでも、必要なクラスをロードすることができます。他のライブラリーのクラスを上書きせずにライブラリーのクラスを共有するための標準化された共通の方法が確立されたことで、Composer をそのまま単独で使用する場合と同じくらい効果的に、Composer を他のライブラリーと一緒に使用できるようになりました。

独自のプロジェクトに合わせて Composer を構成する

Composer のインストール方法と、オートロードの仕組みを理解し、使用する必要があるパッケージを見つけられるようになったところで、独自のプロジェクトに合わせて Composer をセットアップする例を説明します。

まず、新規 PHP プロジェクトを作成するところから始めます。このプロジェクトは、Markdown ファイルを HTML 出力に変換する小さなプログラムです。Packagist で markdown を検索すると、有力候補として michaelf/php-markdown ライブラリーが表示されて、このプロジェクトのホーム・ページの URL が示されます (図 1 を参照)。

図 1. Packagist のライブラリー・エントリー
Packagist に表示された michelf/php-markdown のスクリーンショット
Packagist に表示された michelf/php-markdown のスクリーンショット

プロジェクトに含めるファイルを Composer に指示するために、composer.json という名前の構成ファイルを作成します。この JSON フォーマットのファイルには、各種のコマンドを含めることができますが、最も頻繁に必要となるコマンドは require キーです。このキーに、必要なパッケージの名前とサポートするバージョンを渡します。

{
   "require": {
      "michelf/php-markdown": "1.4.*"
   }
}

これで、アプリケーションのディレクトリー内で composer install を実行することができます。このコマンドを実行すると、Composer は数分で、指定されたライブラリーを vendor ディレクトリーにダウンロードして、このディレクトリーを組み込むオートローダーを作成します。また、Composer は composer.lock という別のファイルも作成します (このファイルについては、後で詳しく説明します)。コマンドと出力は、以下のようになります。

> ls
composer.json
> composer install
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing michelf/php-markdown (1.4.1)
    Downloading: 100%         

Writing lock file
Generating autoload files
> ls -F
composer.json composer.lock vendor/

これで、この michelf/php-markdown パッケージを利用するコードを作成できるようになりました。以下に示す簡潔な PHP スクリプトで、目的の処理が実行されるはずです。

<?php
require 'vendor/autoload.php';

use \Michelf\Markdown;
echo Markdown::defaultTransform(file_get_contents("php://stdin"));

Composer のおかげで、単純で簡潔なソリューションになりました。私が選んだ Markdown パッケージには、たまたま依存関係の追加がありませんでしたが、依存関係を持つパッケージを選んだとしても、Composer が自動的にあらゆる依存関係を同時に取り込んで構成してくれます。

バージョンを指定する

composer.json ファイルには、ソフトウェアに必要なライブラリーをいくつでも追加することができます。さらに、各ライブラリーの許容バージョンを指定することもできます、ソフトウェアが常に機能することを確実にするには、バージョンを指定することが重要です。バージョン番号にワイルドカードを使用すれば、Composer が自動的にライブラリーをアップグレードするようにもなります。前の例では、バージョンを「1.4.*」として指定しました。このように指定したことにより、composer install を実行するたびに、Composer はライブラリーの 1.4 リリースの最新バージョンを検索しますが、1.5 や 2.0 など、1.4 より新しいバージョンは許容しません。常にライブラリーの最新バージョンが取得されるようにするには、「*」を指定します (ただし、使用する API が変更された場合には、これによって問題が発生する可能性があります)。

表 1 に、バージョンの制約を指定する際に使用できるすべてのオプションを一覧として示します。

表 1. パッケージ・バージョンの制約
指定内容説明
正確なバージョン1.0.2パッケージの正確なバージョン
範囲>=1.0>=1.0 <2.0>=1.0 <1.1 || >=1.2比較演算子で、有効なバージョンの範囲を指定することができます。使用できる演算子は、>>=<<=!= です。複数の範囲を定義することができます。その場合、複数の範囲はデフォルトで AND として処理されますが、OR の役割を果たす二重パイプ (||) で範囲を区切ることもできます。
ハイフンで指定する範囲1.0 - 2.0一連のバージョンを包含する範囲を作成します。
ワイルドカード1.0.** ワイルドカードを使用したパターン。1.0.*>=1.0 <1.1 に相当します。
チルダ演算子~1.2.3「次のメジャー・リリース」: 最下位桁の数値を増やすことができます。したがって、>=1.2.3 <1.3.0 に相当します。最下位桁の数値が増えたバージョンは許容されます。
キャレット演算子^1.2.3「次のメジャー・リリース」: チルダ演算子と同様ですが、セマンティックなバージョン管理が想定され、次のメジャー・バージョンまでのすべての変更が許容されます。したがって、>=1.2.3 <2.0 に相当します。

パッケージの安定度

プロジェクトに必要となる正しいライブラリーを取得するように Composer を構成するには、もう 1 つの考慮事項があります。それは、ライブラリー・リリースの安定度を指定することです。最先端のバージョンが必要な場合や、ソフトウェアのテストに利用する場合には、パッケージのベータ版や開発ブランチを要求することができます。安定度を指定するには、require ストリングの末尾に @ を先頭に付けた安定度フラグを追加します。例えば、PHPUnit の最新の開発バージョンを要求する場合、以下のように指定します。

{
   "require": {
      "phpunit/phpunit": "4.8.*@dev"
   }
}

図 1 を見るとわかるように、Packagist には参考として、存在するブランチと、それらのブランチを参照するために使用するストリングが示されます。

バージョンのロック

Composer を使用する最大のメリットの 1 つは、バージョン管理にサード・パーティー・ライブラリーを含める必要がないことです。ソフトウェアの新しいインストールを公開する際に、Composer ですべてのライブラリーを自動的にダウンロードして構成することによって、バージョン管理を簡潔に整理することができます。ただし、問題に突き当たることも考えられます。例えば、Web サイト用に 20 台のサーバーを同時に稼働していて、そのすべてが異なるバージョンのライブラリーを使用している場合を想像してください。コードがデプロイされた時点と、composer install が実行された時点が異なると、このような状況が発生します。あるいはもっと単純な例として、複数の開発者がそれぞれに異なるライブラリーを使用していて、互いのバグを再現できないこともあります。その場合、致命的な結果になりかねません。

Composer は、この問題に対するソリューションを提供しています。「独自のプロジェクトに合わせて Composer を構成する」セクションで、composer install を最初に実行すると、composer.lock ファイルが作成されると説明したことを思い出してください。このファイルは、プロセスでどのライブラリーがインストールされて、どの特定のバージョンがダウンロードされたのかを正確に記録します。プロジェクトをバージョン管理ソフトウェアにコミットするときには、composer.lock ファイルをコミットして、vendor ディレクトリーはコミットしないでください。コードを新しくデプロイする準備がされて、composer install が実行されると、Composer は最初に lock ファイルを探します。このファイルが見つかると、元のインストールとまったく同じ内容をインストールして、インストール間の整合性を確保します。

もちろん、新しいバージョンのコードに移行する方法 (lock ファイルと vender ディレクトリー全体を削除するよりも賢明な方法が望まれます) も必要です。Composer ではこの機能を、update コマンドという形で提供しています。composer update を実行すると、Composer は lock ファイルを使用して、インストール済みソフトウェアのバージョンを JSON ファイルの最新の構成と比較します。構成で許容される、より新しいバージョンのソフトウェアが使用可能な場合 (あるいは、前回のインストール以降に新しいライブラリーが構成に追加された場合)、Composer は代わりにその新しいライブラリーをダウンロードして構成します。

独自のクラスのオートローダーを作成する

Composer には、他にも多くの機能が組み込まれています。これらの機能についてはドキュメントを読んで調べることができますが、最も優れた機能の 1 つとして、開発者は構成の中に独自のクラスを指定して、そのプロジェクトのコードを、Composer が自動的にオートローダーに組み込むようにすることができます。この機能により、開発者は Composer とは独立した独自のオートローダーを作成する必要がなくなります。

以下のコードでは、前の composer.json ファイルを更新して、独自のオートローダーを作成しています。

{
  "require": {
    "michelf/php-markdown": "1.4.*"
  },
  "autoload": {
    "psr-4": {"Converter\\": "src/"}
  }
}

上記の例では、Converter という名前空間を指定し、その名前空間のすべてのクラス・ファイルが相対ディレクトリー src 内に存在していなければならないと指定しています。したがって、Converter\CommandLine という名前のクラスがあるとすると、オートローダーはそのクラスを見つけて、src/CommandLine.php としてファイル・システムに保存することになります。この保存されたファイルが、自動的に生成された PSR-4 準拠のオートローダーになります。

独自のパッケージを提供する

この時点で、Markdown から HTML へのコンバーター・アプリケーションをパッケージとして Packagist に提供することができます (このコンバーターは、再利用できるライブラリーではなくアプリケーションなので、パッケージとして提供するのは実際には理に適っていませんが、この演習では、これがライブラリーであると想定してください)。基本的に、composer.json ファイルを作成したので、このアプリケーション自体をパッケージとしてインストールすることができます。パッケージ名は、vendor/package という形式にする必要があります。したがって、以下のように構成ファイルに追加します。

"name": "EliW/Converter",

他にも追加する価値のある構成がいくつかあります。まず、要求する PHP のバージョンを仮想パッケージ名として指定して、Composer にそれを適用させることができます (他にも多くのオプションがありますが、Composer が標準的なバージョン管理システムのパターンを前提とすることを認めずに、バージョン番号を強制することができます)。また、パッケージ・リストが完全なものに見えるようにメタデータを提供することもできます。PHP のバージョン番号を指定して、このコンバーターを単独の完全なパッケージとしてパッケージ化するには、以下のようにします。

{
  "name": "EliW/Converter",
  "require": {
    "michelf/php-markdown": "1.4.*",
    "php": ">=5.3.0"
  },
}

構成は、これで完了です。アプリケーションを GitHub などのオンライン・バージョン管理システムにコミットした後、Packagist アカウントにログインしてパッケージ情報を送信すれば、他の開発者にこのアプリケーションが公開されて、開発者がそれぞれのプロジェクトに組み込めるようになります。

まとめ

連載 「一新された PHP」の今回の記事では、Composer を使用して、サード・パーティー・ライブラリーからプロジェクトをアセンブルする基本的な方法を説明しました。このオンライン・マニュアルを調べると、それほど一般的に使われていない Composer の機能の詳細を調べたり、Packagist を介さずに独自の内部ライブラリーをホストして複雑なコード・ベースを編成する方法を見つけたりすることができます。

この連載ではこれまで、PHP 自体がどのように進化しているのか、PHP がどのようにして最新のセキュリティー要件を満たしているのか、そして複雑化し続ける最新のコード・ベースを処理するために、最新の依存関係管理システムとパッケージ管理システムをどのように導入しているのかを説明してきました。次回は、PHP エコシステムの進化によって、開発者が PuPHPet を使用してデプロイ環境および開発環境を管理できるようになっている状況について説明します。


ダウンロード可能なリソース


関連トピック

  • PHP プロジェクトのリソース: PHP のスキルを高めるために developerWorks の PHP プロジェクトのリソースを調べてください。
  • Composer: Composer の Web サイトにアクセスしてください。
  • Packagist: 理想の PHP パッケージを調べてください。
  • 「Composer と Packagist」: 「PHP: The Right Way」のこのセクションで、Composer と Packagist を一緒に使用する方法についての詳細を読んでください。
  • PHPDeveloper.org: PHP に関するニュース、意見、コミュニティー情報を入手してください。.
  • php[architect]: PHP の教育に特化した、オンラインで印刷できる雑誌や、最新のニュースを調べてください。
  • さらなる PHP 関連コンテンツ: developerWorks にあるすべての PHP コンテンツをブラウズしてください。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, Open source
ArticleID=1011529
ArticleTitle=一新された PHP: Composer による PHP 依存関係の処理
publish-date=07302015