PHPの名前空間について簡単にまとめてみた

今年の春辺りにようやくPHP5.3がバージョン別シェアの首位に踊りでたそうで、そろそろPHP5.3移行で導入された機能も本格的に取り入れ頃かな?と考えてる人も多いはず。ということで名前空間。

名前空間についてはphp.netのオンラインマニュアルで結構分かりやすくまとめられているのですが、分量がそれなりに多いのでそれを整理・要約してみます。

そもそも名前空間とはなんぞ?

名前空間とは広義において項目をカプセル化する抽象的な概念を指します。PHP: 名前空間の概要 – Manualでは

たとえば、たいていの OS はディレクトリでファイルをグループ化します。 この場合、ディレクトリがその中のファイルの名前空間として機能しています。 具体的に言うと、foo.txt というファイルは /home/greg/home/other の両方に存在することが可能ですが、それらふたつの foo.txt を同じディレクトリに配置することはできません。 さらに、/home/greg ディレクトリの外から foo.txt にアクセスするには、ディレクトリ名をファイル名の前につけて /home/greg/foo.txt としなければなりません。 プログラミングの世界における名前空間も、この延長線上にあります。

と例えられています。これまでPHP の組込みのクラス・関数・定数やサードパーティのクラス・関数・定数などの名前が競合してしまう問題を回避するために、クラスや関数、定数などに競合しないと思われる長い名前を付けていた面倒を解決する方法として導入されました。

PHPで名前空間を使ってみる

PHPの名前空間を宣言するにはキーワード namespace を用います。具体的には

<?php
namespace MySample;

class MyClass {
/* ... */
}
?>

と記述したコードがあったとすると、ここに書かれた MyClass は名前空間 MySample の影響下に入ります。要は namespace を使用することで宣言された名前空間は、原則それ以降のコードがその名前空間の領域となります。

なお、PHP のコードなら名前空間に含めることができます。ただし実際に名前空間の影響を受けるのは

  1. クラス
  2. インターフェイス
  3. 関数
  4. 定数

の4種類です。

また通常、他のコードより前にファイルの先頭で名前空間を宣言する必要があります。例えば、

<html>
<!-- 以下いろいろHTMLの記述が続く -->
<?php
namespace NewNamespace; // Fatal Errorが発生する
?>
</html>

のように HTML の途中に PHPコードを埋め込んで、その中で名前空間を宣言するといったことはできません。例外として

<?php
namespace MySampleSpace01 {
	function sample_function () {
		/* ... */
	}
}

namespace MySampleSpace02 {
	function sample_function () {
		/* ... */
	}
}
?>

のように一つのファイルで複数の名前空間を宣言する場合に限っては、ファイル途中で namespace を使用することができます。但し PHP: 同一ファイル内での複数の名前空間の定義 – Manual にて 複数の名前空間をひとつのファイルに記述するようなコーディングはできるだけ避けるべき、とされている点に注意ください。

名前空間に属する関数、クラスなどを参照する

ある名前空間内の関数などを呼び出す場合は以下のように、名前空間を付加した修飾名で呼び出します。

<?php // test01.php
namespace My\Space;
function echo_message () {
    echo "hello, My Space.\n";
}
?>

というファイルがあったとして、次のファイルから名前空間 My\Space に属す関数 echo_message() を呼び出す例です。

<?php // test02.php
require_once 'test01.php';
\My\Space\echo_message();
?>

最初に名前空間を OS のファイルシステムに喩えた説明を引用しましたが、同じように相対パスのように、今いる名前空間を基準に名前空間が補正されます。例えば先の test02.php 同様、test01.php をrequire しますが、

<?php // test02_01.php
namespace Sub\Space;

require_once 'test01.php';
My\Space\echo_message(); // fatal error.
?>

test02_01.php だと、今いる名前空間が Sub\Space で、且つ OS のファイルシステムでいうところの相対パス に相当する My\Space\echo_message() で参照する指定となります。結果、Sub\Space\My\Space\echo_message() を参照しにいって見つからないので、Call to undefined function と怒られます。

詳しくは PHP: 名前解決のルール – Manual でまとめられています。

名前空間とグローバル空間

名前空間の定義されていない領域での PHP の記述はグローバル空間と呼ばれる空間に配置されます。

グローバル空間とは名前空間に対応する前の PHP のコードを記述していた領域を指す……って文で書いても今ひとつ分かりにくいですよねw

<?php // file01.php
// namespace の宣言がないのでこっちは全域がグローバル空間

require_once 'file02.php';

\My\Space\echo_message(); // 名前空間 \My\Space\echo_message() が呼ばれる

function echo_message () {
    echo "hello, World!\n";
}
?>
<?php // file02.php
namespace My\Space;

// namespace を用いいて宣言されたので My\Space の名前空間

echo_message();  // 名前空間 \My\Space\echo_message() が呼ばれる
\echo_message(); // file01.php に記述された グローバル空間の echo_message() が呼ばれる

function echo_message() {
    echo "hello, My Space.\n";
}

class MySpaceClass {
}
?>

どっかの名前空間からグローバル空間のクラスや関数にアクセスする場合は冒頭に \ を付けます。

注意したいのは PHP: グローバル空間 – Manual のサンプルにもあるように、名前空間内に PHP 標準関数と同名の関数名を定義しちゃうと色々面倒です(苦笑)。裏を返すと PHP 標準関数に存在する関数名も特別扱いされることなく名前空間の影響を受ける、ということでもあります。

エイリアス / インポート

ある名前空間から別の名前空間のクラスや関数を呼び出す際、現在の名前空間との関係を逐次意識しながら記述したり、あるいは

<?php
namespace AnySpace;

\My\Space\Is\Very\Small\echo_message();

// ...
?>

などといちいち完全修飾名で呼び出さないといけないとなるとかなり煩雑なので、PHP の名前空間には use 演算子を用いて既に定義された名前空間にエイリアスを指定したり、あるいは別の名前空間に属するクラスをインポートする機能があります。

まず名前空間にエイリアスを張る例。

<?php
require_once 'file02.php';

use My\Space as MySpace;

MySpace\echo_message();

$obj = new MySpace\MySpaceClass();
echo get_class($obj) ."\n";
?>

この例では名前空間 My\Space に MySpace という別名が与えられ、名前空間名 My\Space の代用として利用できることがわかります。

次に別(ここでは file02.php の My\Space)の名前空間に属するクラスをインポートする例。

<?php
require_once '20130806_02.php';

use My\Space\MySpaceClass as MyClass;

$obj01 = new MyClass();
echo get_class($obj01) ."\n";

use My\Space\MySpaceClass;

$obj02 = new MySpaceClass();
echo get_class($obj02) ."\n";

function echo_message () {
    echo "hello, World!\n";
}
?>

こちらの例の場合、名前空間 My\Space に属す MySpaceClass に直接エイリアスを定義し、且つその別名で My\Space\MySpaceClass を呼び出せることが分かります。また、as を使わなかった場合は

use My\Space\MySpaceClass as MySpaceClass;

と同等となり、一見クラス名だけで My\Space\MySpaceClass を呼び出せるような挙動となることも分かります。

まとめ

長くなった割りには要約になってないにも関わらず駆け足感が強いのですが、PHPのオンラインマニュアルの説明は結構分かりやすいので参照してみてください。そのきっかけとなれば幸いです。

その他、PHPのnamespace(名前空間) | kudox.jp も分かりやすく説明されています。

参照URL