「コナンが私の手本だよ。」と、私が夕食の食卓で話したとすると、息子はすぐに私が映画「コナン・ザ・グレート (原題: Conan the Barbarian)」の主人公を手本としているのだと思い、一方、妻は私が深夜のトークショーの司会を務めるコナン・オブライエン (Conan O'Brien) のようになりたがっているのだと思うでしょう。このような話の背景の曖昧さは、IT の世界では名前の衝突として知られています。多くの言語には名前の衝突を防ぐための仕組みがあり、PHP V5.3 にもこの仕組みが導入されています。PHP では、新しい名前空間の機能によって名前が衝突する問題を解決しています。もちろん、PHP で衝突を防いでいる名前は人々の名前ではなく、クラスや関数、定数の名前です。
この記事では、なぜ皆さんの次のプロジェクトで名前空間の使用を検討する必要があるのかを説明します。まず、名前空間のセマンティクスの概要、ベスト・プラクティス、および名前空間を使用する簡単な Model-View-Controller (MVC) アプリケーションの例について説明します。次に、名前空間が Eclipse、NetBeans、および Zend Studio でどのようにサポートされているかについて明らかにしますが、特に Eclipse で名前空間を使用する詳細な方法について取り上げます。
名前空間は必要なのか
PHP 言語の強みはその単純さです。したがって、皆さんが PHP の初心者なのであれば、名前空間はいずれ理解する必要がある概念の 1 つにすぎません。しかし、皆さんが以下のいずれかに当てはまる場合には、名前空間の使用を検討する必要があります。
- 何百という PHP ファイルを持つ大規模なアプリケーションを開発する場合
- アプリケーションがコーディング・チームによって開発されている場合
- PHP V5.3 と名前空間を使用するフレームワークの使用を計画している場合
- 他の言語 (Java™、Ruby、Python など) では名前空間 (あるいはパッケージのような類似機能) を使用していた場合
比較的小規模のアプリケーションを 1 人で開発している場合には、名前空間は必要ないかもしれません。しかし、それ以外の人々にとっては、名前空間を使用することでクラス構造をすっきりと体系化することができ、もちろん、名前の衝突を防ぐことができるようになります。この 2 つの理由から、多くのフレームワーク開発者は名前空間を採用するようになっています。例えば Zend Framework (巨大な PHP フレームワーク) は Zend Framework V2.0 で名前空間を使用しています。
簡単な概要
名前空間により、名前にコンテキストを追加することができます。例えば、リスト 1 に示す 2 つのクラスでは名前が衝突しています。
リスト 1. 名前空間を使用しないと衝突が起きる、同じ名前の 2 つのクラス
class Conan { var $bodyBuild = "extremely muscular"; var $birthDate = 'before history'; var $skill = 'fighting'; } class Conan { var $bodyBuild = "very skinny"; var $birthDate = '1963'; var $skill = 'comedy'; }
名前空間を指定するためには、ソースの最初の文として、名前空間宣言を追加するだけです (リスト 2)。
リスト 2. 名前空間を使用することで衝突を防ぐことができる、同じ名前の 2 つのクラス
<?php namespace barbarian; class Conan { var $bodyBuild = "extremely muscular"; var $birthDate = 'before history'; var $skill = 'fighting'; } namespace obrien; class Conan { var $bodyBuild = "very skinny"; var $birthDate = '1963'; var $skill = 'comedy'; } $conan = new \barbarian\Conan(); assert('extremely muscular born: before history' == "$conan->bodyBuild born: $conan->birthDate"); $conan = new \obrien\Conan(); assert('very skinny born: 1963' == "$conan->bodyBuild born: $conan->birthDate"); ?>
上記のコードは問題なく実行されますが、なぜ 2 つの Conan が同時に機能するかを説明する前に、2 つの点を指摘しておきましょう。第 1 に、このコードが想定どおりに動作していることを示すためにアサーションを使用しています。第 2 に、ここでは1 つのソース・ファイル内で複数の名前空間を宣言するという、絶対にしてはならないことをしています。
名前空間により、2 つの Conan に一意の修飾子を提供することができます。このコードは、無骨な破壊者である Conan
を参照しているのか、それとも深夜のトークショーの司会者である Conan
を参照しているのかを明確に示しています。インスタンス化のための構文には、以下のようにバックスラッシュ (\
) が使用され、その後に名前空間の名前が続いていることに注意してください。
$conan = new \barbarian\Conan();
および
$conan = new \obrien\Conan();
これらの修飾子は Windows® スタイルのディレクトリー修飾子のように見えますが、そのように考えても問題ありません。その 1 つの理由は、名前空間は (ディレクトリーと同様に) 相対参照と絶対参照の両方をサポートしているからです。またもう 1 つの理由は、名前空間と一致するディレクトリーに、クラス・ファイルのソースを配置することがベスト・プラクティスだからです。
名前空間を使用する
現実的には、2 つの Conan クラスを barbarian と obrien というディレクトリーに分け、この 2 つのクラスを別の PHP ファイルから参照する必要があります。PHP の名前空間を参照するには、以下の 3 つの方法があります。
- クラス名の接頭辞として名前空間を指定する
- 名前空間をインポートする
- 名前空間にエイリアスを付ける
第 1 の方法を使用するには、単純にクラス名の接頭辞として名前空間を指定します (当然ですが、名前空間の指定はソース・ファイルをインクルードした後に行います)。
include "barbarian/Conan.php"; $conan = new \barbarian\Conan();
この方法は非常に単純ですが、大規模なアプリケーションの場合には何度も名前空間を入力しなければならないという問題があります。また入力が面倒なことの他に、コード・ベースが必要以上に雑然としたものになります。第 2 の方法では、PHP V5.3 の予約語である use を使用して以下のように名前空間をインポートします。
include "barbarian/Conan.php"; use barbarian\Conan; $conan = new Conan();
第 3 の方法では、以下のように名前空間のエイリアスを指定します。
include "barbarian/Conan.php"; use \barbarian\Conan as Cimmerian; $conan = new Cimmerian();
(ちなみに、Cimmerian はコナン・ザ・グレートの主人公の別名として知られています。)
上記の 3 つの方法に共通する問題は、include
文を使用している点です。include
を不要にするためには __autoload
関数を使用します。PHP のマジック・メソッドである __autoload
関数は、まだソース・ファイルにインクルードされていないクラスが参照されると呼び出されます。リスト 3 のコードは autoload.php というファイルに配置します。
リスト 3. ソース・ファイルを動的にインクルードする __autoload
マジック関数
<?php function __autoload($classname) { $classname = ltrim($classname, '\\'); $filename = ''; $namespace = ''; if ($lastnspos = strripos($classname, '\\')) { $namespace = substr($classname, 0, $lastnspos); $classname = substr($classname, $lastnspos + 1); $filename = str_replace('\\', '/', $namespace) . '/'; } $filename .= str_replace('_', '/', $classname) . '.php'; require $filename; } ?>
次に autoload.php をソースにインポートします。
require_once "autoload.php"; use \barbarian\Conan as Cimmerian;
オートローダーの大きなメリットは、クラスごとに include
文を作成する必要がないことです。ただし、本来 PHP の名前空間はクラスに対してだけではなく、関数と定数にも使用できますが、オートローダーの方法はクラスに対してだけ使用できることに注意してください。オートローダーは非常に便利であり、関数をコーディングする代わりに、適切な名前が付けられたユーティリティー・クラスの中にメソッドを作成し、また不変クラスの中には定数を配置することができるようになります。
MVC について考察する
コナン・ザ・グレートでコナンの両親を殺害した首領が殺されるのを、コナン・オブライエンが冷笑しているのは忘れて、簡単な MVC アプリケーションの例に移りましょう。名前空間のメリットを生かすためには、コード行の入力を始める前に命名規則を決める必要があります。一般的なベスト・プラクティスは、名前空間ツリーを使用することです。名前空間には、上位レベルの名前空間とサブ名前空間があることを理解してください。皆さんの会社に複数のアプリケーションがある場合には、会社の名前を上位レベルの名前空間として使用し、サブ名前空間をアプリケーション用に使用すると便利です。そして、さまざまなディレクトリーが含まれるレベルでは、それらのディレクトリーの名前によって、各ディレクトリーに含まれている PHP クラスのアプリケーションでの機能を明確に示すようにするのです。例えば、上位レベルの会社の名前空間には denoncourt、最初のサブレベルには retail、それに続くレベルには機能名を指定します (リスト 4)。
リスト 4. ネストされたサブ名前空間を含むことができるような名前空間の設計
/denoncourt /retail /common /controller /model /utility /view
controller
、model
、および view
というサブ名前空間は当然、MVC アーキテクチャー用ですが、私が追加した utility
と common
というサブ名前空間は、他のサブ名前空間のどれにも明確に当てはまらなかった一般的なクラスに使用するためのものです。
では早速、簡単な MVC アプリケーションのコードに移りましょう。リスト 5 に、ルート・フォルダーに配置される index.php のコードを示します。
リスト 5. controller クラスを使用する MVC アプリケーションの index.php
<?php require "autoload.php"; use denoncourt\retail\controller as Control; $controller = new Control\Controller(); $controller->execute(); ?>
名前空間が長いので Control
というエイリアス名が使用されていることに注意してください。私は名前空間を使用する場合には、エイリアスを使用するのを好みますが、その理由は 2 つあります。第 1
の理由は、あとで名前空間をリネームする場合、ソース・ファイルごとにコードを 1 行変更するだけで済むからです。そして第 2
の理由は、クラスをインスタンス化する場合には名前空間を完全修飾することがベスト・プラクティスですが、Control\Controller()
を使用すると実質的には \denoncourt\retail\controller\Controller()
を使用したのと同じことになるからです。
もちろん、以下のように上位レベルの名前空間のエイリアスを作成し、サブ名前空間の名前を使用してクラスをインスタンス化してもよかったことに注意してください。
use denoncourt\retail as Retail; $controller = new retail\controller\Controller();
この方法は同じソース・ファイルの中で、複数のレベルの名前空間を参照する場合に便利です。リスト 6 に示すコードでは、denoncourt/retail/controller ディレクトリーの中に Controller.php を作成しました。
リスト 6. ユーザー入力に基づくアクションを記述する MVC の controller クラス
<?php namespace denoncourt\retail\controller; use denoncourt\retail as retail; class Controller { public function execute() { switch ($_GET['action']) { case 'showItem' : $item = new retail\model\Item(); require "denoncourt/retail/utils/format.php"; require "denoncourt/retail/view/item.php"; break; } } } ?>
リスト 7 に示すコードでは、denoncourt/retail/model の中に Item.php を作成しました。
リスト 7. model サブ名前空間に属する MVC の Item クラス
<?php namespace denoncourt\retail\model; class Item { public $itemNo = '123'; public $price = 2.45; public $qtyOnHand = 87; } ?>
リスト 8 に示すコードでは、denoncourt/retail/utils の中に format.php を作成しました。
リスト 8. 関数に名前空間を指定する方法を示す PHP の dollar 関数
<?php namespace denoncourt\retail; function dollar($dollar) { return "\$$dollar"; } ?>
先ほど触れたように、私はフォーマット関数をユーティリティー・クラスの中に入れるのを好みます (そうすればオートローダーによってコードのインポートが処理されるため、format.php 用に require 文をコーディングする必要がなくなるからです)。
最後に、denoncourt/retail/views にある item.php というビュー・ページのコードをリスト 9 に示します。
リスト 9. controller でインスタンス化された model を表示する item ページ
<html> <head> <style> dt { float:left; clear:left; font-weight:bold; margin-right:10px; width:15%; text-align: right; } dd { text-align:left; } </style> </head> <body> <dl> <dt>Item No:</dt><dd><?php echo "$item->itemNo"; ?></dd> <dt>Price:</dt><dd> <?php echo \denoncourt\retail\dollar($item->price); ?> </dd> <dt>Quantity On Hand:</dt><dd><?php echo "$item->qtyOnHand"; ?></dd> </dl> </body> </html>
item ページでは、dollar
関数が \denoncourt\retail\ という名前空間で、どのように修飾されているかに着目してください。
フォールバック
ソース・ファイルに名前空間宣言がある場合、クラス、関数、および定数への参照にはすべて、名前空間のセマンティクスを使用します。PHP
は、修飾されていないクラス、関数、または定数に遭遇すると、フォールバックと呼ばれる動作を実行します。ユーザー・クラスでフォールバックが実行されると、コンパイラーはそのクラスが現在の名前空間に属していることを前提に処理を行います。名前空間が指定されていないクラスを参照するためには、バックスラッシュを
1 つ付ける必要があります。例えば、PHP の Exception
クラスを参照するためには $error = new \Exception();
のようにします。PHP 標準ライブラリーのクラス (ArrayObject
、FindFile
、KeyFilter
など) を使用する場合には、そのことを頭に入れておいてください。
関数や定数の場合、その関数または定数が現在の名前空間に属していない場合には、PHP のフォールバック・メカニズムによって PHP
の標準関数にフォールバックします。従って、例えば皆さんが独自の strlen
関数をコーディングした場合、PHP
はその strlen
関数を使用することになるでしょう。しかし、PHP の標準関数である strlen
を (例えば、皆さん独自の strlen
の実装の中で) 使用したい場合には、strlen
関数の前にバックスラッシュを付けて呼び出す必要があります (リスト 10)。
リスト 10. PHP の標準関数を指定する場合、グローバルな名前空間を示すためにバックスラッシュで修飾するコード
<?php namespace denoncourt\retail; function strlen($str) { return \strlen(); } ?>
名前空間でのグローバル変数と文字列
動的なメソッドをコーディングしたい場合、"denoncourt\retail\controller"
のように二重引用符で囲んだ文字列の中に名前空間を配置したくなるかもしれません。しかし、これらのバックスラッシュをエスケープし、"denoncourt\\retail\\controller"
のようにする必要があることを忘れないでください。次善の策としては
'denoncourt\retail\controller'
のように、単純に単一引用符を使用する方法もあります。
動的プログラミングを行う場合、PHP V5.3 には __NAMESPACE__
という新しいグローバル変数があることを忘れないでください。名前空間を入力する代わりに、以下のように __NAMESPACE__ を使用するようにします。
$echo 'I am using this namespace:'.__NAMESPACE__;
IDE での名前空間のサポート
主要な IDE のほとんどは、既に PHP V5.3 をサポートしています。NetBeans V6.8 は名前空間を十分にサポートしているとともに、コード補完機能を備えているだけでなく、ベスト・プラクティスを基にコードを改善するための提案も行います。例えば PHP の名前空間では、相対参照ではなく絶対参照を使用してコード内の名前空間を完全修飾することがベスト・プラクティスです。相対的な名前空間修飾子を使用するコードを作成すると、NetBeans はコード左端の余白部分に電球のアイコンを表示します。そのアイコンの上にマウス・ポインターを重ねると、NetBeans は変更候補を提案するツール・チップを表示します。そのアイコンをクリックすると、NetBeans はコードを変更してくれます。
Zend Studio にも同じような機能が用意されています。名前空間を使い始めることをためらっている人は、IDE をアップグレードし、お気に入りの IDE のヘルプを参照して名前空間を試してみてください。場合によっては IDE をアップグレードする必要もないかもしれません。多くの IDE は PHP V5.3 の機能を 1 年以上も前から提供しているからです。
PDT (PHP Development Tools) V2.1 も確実に名前空間をサポートしています。PDT は Eclipse 用のプラグインです。PDT をインストールするための参考資料へのリンクが「参考文献」セクションにあります。
名前空間のサポートを有効にするには、まず Eclipse/PDT に PHP V5.3 を使用することを指示する必要があります。そのためには、アプリケーションのメイン・メニューから「Window (ウィンドウ)」 > 「Preferences (設定)」の順にクリックします (図 1)。ツリー・ペインで「PHP」を展開し、「PHP Interpreter (PHP インタープリター)」を選択します。そして PHP のバージョンを「PHP 5.3」に変更し、「OK」をクリックします。
図 1. Eclipse の PDT プラグインでインタープリターを PHP V5.3 に設定する様子
PHP プロジェクトを作成するには、「File (ファイル)」 > 「New Project
(新規プロジェクト)」の順にクリックし、「PHP」ノードを展開したら、「PHP Project (PHP
プロジェクト)」をクリックします。PHP ファイルを作成するには、単純に「PHP Explorer (PHP
エクスプローラー)」でプロジェクトを右クリックし、「PHP file (PHP ファイル)」をクリックします。PDT
は名前空間を示すキーワードの namespace
と use
に、適切な構文強調表示を適用します (図 2)。
図 2. PDT では構文強調表示機能を使用して名前空間のキーワードが強調表示され、「PHP Explorer (PHP エクスプローラー) 」ビューと「Outline (アウトライン)」ビューに名前空間が表示されている様子
PDT で名前空間を「PHP Explorer (PHP エクスプローラー)」ビューと「Outline
(アウトライン)」ビューに表示すると、名前空間がさまざまなクラスに割り当てられている様子が表示されて便利です。また PDT は、IDE
に備わっている機能として期待される、コード補完機能も提供しています (図 3)。use
文を入力すると、PHP によってコード補完機能が呼び出されます。
図 3. PDT では名前空間に対してもコード補完機能が提供されている様子
また、クラス名を入力していくと、PDT によりコード補完ウィンドウがポップアップ表示されます。例えば 「new
Item
」と入力すると、PDT は「Item � denoncourt\retail\item
」と記されたウィンドウが表示されます。
「denoncourt\retail\item」を選択すると、PDT によって以下のように必要な use 文と修飾子が、インスタンス化を実行する行に挿入されます。
use denoncourt\retail\model; new model\Item();
素晴しいことに、「new Conan
」と入力すると、PDT は以下の内容のウィンドウを表示します。
Conan � obrien Conan � barbarian
このウィンドウから適切な Conan を選択することができます。私は再び 2 人のコナンに夢中になっている状態に戻ってしまったので、そろそろまとめに入ることにしましょう。
まとめ
まだ名前空間を使い始めることに、皆さんがためらいを感じているのであれば、名前空間の習得をもう 1 年延期してしまう前に、皆さんのお気に入りの IDE に PHP V5.3 のサポートを追加し、名前空間を試してみることをお勧めします。命名規則については、完璧な方式を考え出そうと苦労するよりも、まずは単純な規則を設定することの方が重要です。私個人としては、長年 Java での開発に従事してきた経験から、Java の命名規則に従うのが好みであり、PHP の名前空間にキャメル記法の名前を使用し、アンダーバーは使用しません。皆さんの次の PHP プロジェクトでも名前空間を使用することで、すっきりと体系化されたコードにすることができ、さらには主要な言語のほとんどで一般的となっている機能を使いこなせるようになります。そして、PHP V5.3 (特に名前空間) を既に使用しているフレームワークのメリットを享受する準備が整うことになるでしょう。
ダウンロード
内容 | ファイル名 | サイズ |
---|---|---|
Sample scripts | os-php-5.3namespaces_code.zip | 6KB |
参考文献
学ぶために
- PHP Architect の記事、「PHP 5.3 namespaces for the rest of us」を読み、名前空間について詳しく学んでください。
- Nathan A. Good が developerWorks に寄稿した記事、「PHP での名前空間を適切に作成する」を読んでください。
- PHP での名前空間の基本を学んでください。
- PHP Namespace FAQ で PHP に関する質問の答えを見つけてください。
- PHP Namespace Support in NetBeans V6.8 で良く学んでください。
- PDT のインストール・ノートを入手してください。
- PHP.net には PHP 開発者のためのリソースが集まっています。
- 「Recommended PHP reading list」を調べてみてください。
- developerWorks の PHP に関するすべての記事に目を通してください。
- developerWorks を Twitter でフォローしてください。
- IBM developerWorks の PHP project resources を利用して PHP のスキルを磨いてください。
- developerWorks podcasts では、ソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
- PHP でデータベースを使うのであれば、Zend Core for IBM を調べてみてください。これはシームレスでそのまま使用でき、インストールも容易な PHP の開発環境であり本番環境でもあります。この環境は IBM DB2 V9 をサポートしています。
- developerWorks の Technical events and webcasts で最新情報を入手してください。
- IBM オープンソース開発者にとって関心のある、世界中で今後開催される会議や業界展示会、ウェブキャスト、その他のイベントについて調べてみてください。
- developerWorks の Open source ゾーンをご覧ください。オープンソース技術を使った開発や、IBM 製品でオープンソース技術を使用するためのハウ・ツー情報やツール、プロジェクトの更新情報など、豊富な情報が用意されています。また最も人気のある記事やチュートリアルもご覧ください。
- 無料の developerWorks On demand demos を視聴して、IBM とオープンソース技術、そして製品機能を学んでください。
製品や技術を入手するために
- Eclipse PDT V2.1 をダウンロードしてください。
- 皆さんの次のオープンソース開発プロジェクトを IBM ソフトウェアの試用版を使用して革新してください。ダウンロード、あるいは DVD で入手することができます。
- BM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版を調べて、DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を入手してください。
議論するために
- developerWorks コミュニティーの PHP Developers グループに参加し、他の PHP 開発者と議論してください。
- developerWorks コミュニティーに参加してください。開発者向けのブログ、フォーラム、グループ、ウィキなどを利用して、他の developerWorks ユーザーと議論してください。
- developerWorks blogs から developerWorks コミュニティーに加わってください。
- developerWorks の PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS) に加わってください。
コメント
IBM PureSystems
IBM がどのように IT に革命をもたらしているのかをご自身でお確かめください
Knowledge path
developerWorks の Knowledge path シリーズでは、テーマ別の学習資料をご提供しています
ソフトウェア評価版: ダウンロード
developerWorksでIBM製品をお試しください!