✍️

PHPの名前空間について

2022/09/18に公開約3,300字

はじめに

PHPには、2009年にver. 5.3.0がリリースされるまで名前空間という概念がなかったため、ライブラリやアプリケーションの開発者は、PHPに組み込まれている関数やクラス名や他の人が作ったライブラリなどとの名前衝突・競合を避けるため、モジュール名をプレフィックス(接頭辞)としてつけるなどの工夫をしてきた。

Usage

名前空間を使うことで、名前衝突を避けることができる。長ったらしく命名していたクラス名や関数名ともおさらば。

名前空間を用いた例を見ていこう。
以下のように、組み込まれるファイルに名前空間Food/Sweetsとそれに属すCakeクラスを定義する。

<?php
// Cake.php

namespace Food/Sweets;

class Cake
{
  //
}

require_onceによってCake.phpを読み込んだ場合、Cakeクラスには次のような名前空間をつけてアクセスする。

<?php
// program.php

require_once 'Cake.php';

$c = new Food\Sweets\Cake();

名前空間は、いわばディレクトリのようなもの。
ディレクトやファイルを、機能や用途別に作成・整理するかのように用いる。

名前空間を使用する際のポイント

- 名前空間の区切りにはバックスラッシュ\を用いる。(例: Food\Sweets)
- 名前空間を定義した場合、グローバルな関数やクラスは先頭にバックスラッシュ\をつけ、グローバルな名前空間から参照しなければならない。

名前空間において、クラス名や名前空間の名前は、次のように言葉の定義がされている。

  • 非修飾名 ... 名前区切り\を含まない識別子(例: Cake)
  • 修飾名 ... 名前空間区切り\を含む識別子(例: Food\Sweets)
  • 完全修飾名 ... 名前空間区切り\から始まる識別子(例: \Food\Sweets)

名前空間の定義

名前空間は次のように定義する。基本的に、名前空間の宣言より前にはコメント以外の出力や文が存在してはいけない。

namespace 名前空間;

名前空間を機能によって階層化させる場合、バックスラッシュ\で区切る。

namespace 名前空間\サブ名前空間;

名前空間の影響を受けるのは、

  • クラス
  • 関数
  • 定数(constによって定義されるものに限る)

の3種類。
変数やdefineによって定義される定数には名前空間は適用されず、名前空間がない場合と、同様に参照される。

<?php

namespace Project\Module;

class Directory{} // Project\Module\Directory クラス
function file() {} // Project\Module\file 関数
$var = 0x01; // 変数に名前空間は適用されない

別の名前空間から参照する際は、常に完全修飾名の指定をしなければならない。
これは、グローバルに定義されている(組み込みの定義済みの)クラスに対しても同様のことがいえる。

<?php

namespace Other;

require_once 'Project/Module/Directory.php';

$dir1 = new \Project\Module\Directory(); // Project\Module\Directory クラス
$dir2 = new \Directory(); // 組み込みのDirectory クラス

グローバルな空間からは、修飾名による相対的な指定ができる。(先頭の\は必要ない)。

<?php
// 名前空間が宣言されていない

require_once 'Project/Module/Directory.php';

$dir = new Project\Module\Directory();

1つのファイルに複数の名前空間の定義する

名前空間を1つファイルの中に複数定義する場合には。2つの方法がある。

  1. 単純にnamespace宣言を複製する方法
<?php

namespace Project\Module;
// ここはProject\Module 名前空間の中

class Directory {} //Project\Module\Directory クラス

namespace Projet\Module2;
// ここはProject\Module2 名前空間の中

class Directory {} // Project\Module2\Directory クラス
  1. {}で囲む方法
<?php

namespace Project\Module {
  // ここはProject\Module 名前空間の中

  class Directory {} // Project\Module\Directory クラス

  namespace Project\Module2;
  // ここはProject\Module2 名前空間の中

  class Directory {} // Project\Module2\Directory クラス
}

この構文を用いる場合、名前空間の{}の外には出力や文があってはならない。混乱を避けるためには、複数の名前空間を1つのファイルの中に定義する場合には、中括弧を用いるほうがよい。

インポートのルール

名前空間を使う歳、別の名前空間やそれに属するクラスをuseキーワードを使ってインポートしたり、asを用いることによって別名をつけることができる。
※定数と関数はこれによってインポートすることはできない。

use \クラス名;
use 名前空間;
use 名前空間 as 別名;
use 名前空間\クラス名;

例えば、次のように記述することにより、Projecrt\Module2名前空間をAnotherModuleという別名で扱うことができるようになる。

<?php

namespace Project\Module;
use Project\Module2 as AnotherModule;

$obj = new AnotherModule\SomeClass(); // new Project\Module2\SomeClass()と等価

asを使わなかった場合、名前空間区切りで区切られた最後の非修飾名でインポートすることと等価。

use Project\Module2;
// これは、use Project\Module2 as Module2; と等価

名前空間名だけでなく、クラス名もインポートすることができる。
グローバルに定義されているクラスなども、同様にuseでインポートすることができる。

namespace Project\Module;

// use \Directory as Directoryと等価であり、グローバルなクラスに「\」なしでアクセスできるようになる
use \Directory;

$dir = new Directory('./');

// 別の名前空間に定義されたBazクラスを、Bazという名前でアクセスできるようにする
use Foo\Bar\Baz;
$baz = new Baz();

引用文献

小川雄大 . パーフェクトPHP . 技術評論社 , 2010年11月12日出版

Discussion

ログインするとコメントできます