namespace / use(名前空間)
名前空間でクラスや関数の衝突を防ぎ、大規模なコードベースを整理するには『PHP』の『namespace』と『use』が便利です。同名のクラスが複数のライブラリに存在する場合でも、名前空間を使えば安全に共存させることができます。
構文
// 名前空間を宣言します(ファイルの先頭、<?php の直後に記述します)
namespace 名前空間名;
// 階層構造(サブ名前空間)を持てます
namespace 上位\下位;
// 他の名前空間のクラスをインポートします
use 名前空間名\クラス名;
// エイリアス(別名)を付けてインポートします
use 名前空間名\クラス名 as 別名;
// 複数のクラスをまとめてインポートします(PHP 7以降)
use 名前空間名\{クラス名1, クラス名2};
構文一覧
| 構文 | 概要 |
|---|---|
| namespace 名前空間名; | 現在のファイルに名前空間を設定します。ファイル先頭(<?php の直後)に1つだけ記述します。 |
| use クラス名; | 他の名前空間のクラス・インターフェース・トレイトをインポートします。以降は短縮名で使用できます。 |
| use クラス名 as 別名; | インポート時にエイリアスを付けます。同名クラスが競合する場合に使用します。 |
| use 名前空間\{クラス1, クラス2}; | 同じ名前空間の複数クラスをまとめてインポートします(PHP 7以降)。 |
| use function 名前空間\関数名; | 名前空間内の関数をインポートします。 |
| use const 名前空間\定数名; | 名前空間内の定数をインポートします。 |
| \クラス名 | 先頭にバックスラッシュを付けるとグローバル名前空間(名前空間なし)のクラスを参照します。 |
サンプルコード
名前空間の基本とuseによるインポート
src/Yakuza/Character.php
<?php
// 龍が如くシリーズのキャラクターを管理する名前空間を宣言します
// ファイルの先頭(<?php の直後)に namespace を記述します
namespace Yakuza;
class Character
{
public function __construct(
private string $name,
private string $clan,
private int $level
) {}
public function getProfile(): string
{
return "{$this->name}({$this->clan} / Lv.{$this->level})";
}
public function getName(): string
{
return $this->name;
}
}
src/Yakuza/Combat/Style.php
<?php
// サブ名前空間(Yakuza\Combat)を宣言します
// バックスラッシュ(\)で階層を区切ります
namespace Yakuza\Combat;
class Style
{
// 戦闘スタイルの名称と説明を定義します
private static array $styles = [
'brawler' => '喧嘩師スタイル。バランスの取れた基本スタイルです。',
'beast' => '猛牛スタイル。物をつかんで豪快に戦うスタイルです。',
'rush' => '電光石火スタイル。素早いパンチラッシュが得意なスタイルです。',
'legend' => '龍のスタイル。圧倒的な威力を誇る究極スタイルです。',
];
public static function getDescription(string $key): string
{
return self::$styles[$key] ?? '不明なスタイルです。';
}
}
index.php
<?php
// use でクラスをインポートすると、以降は短縮名で使用できます
// インポートなしで使う場合は完全修飾名(\Yakuza\Character)が必要です
use Yakuza\Character;
use Yakuza\Combat\Style;
// インポート後はクラス名だけでインスタンス化できます
$kiryu = new Character('桐生一馬', '東城会', 99);
$majima = new Character('真島吾朗', 'マジマ組', 99);
$saejima = new Character('冴島大河', '東城会', 95);
echo $kiryu->getProfile() . "\n";
echo $majima->getProfile() . "\n";
echo $saejima->getProfile() . "\n";
// staticメソッドも短縮名で呼び出せます
echo Style::getDescription('legend') . "\n";
echo Style::getDescription('brawler') . "\n";
実行すると次のように出力されます。
php index.php 桐生一馬(東城会 / Lv.99) 真島吾朗(マジマ組 / Lv.99) 冴島大河(東城会 / Lv.95) 龍のスタイル。圧倒的な威力を誇る究極スタイルです。 喧嘩師スタイル。バランスの取れた基本スタイルです。
エイリアス(use ... as)と複数クラスのまとめインポート
src/Kamurocho/Character.php
<?php
// 別の名前空間にも同名の Character クラスを定義します
// 同名クラスが複数存在する場合、use ... as でエイリアスを付けて区別します
namespace Kamurocho;
class Character
{
public function __construct(
private string $name,
private string $role
) {}
public function describe(): string
{
return "[神室町] {$this->name}({$this->role})";
}
}
src/Kamurocho/Item.php
<?php
namespace Kamurocho;
class Item
{
public function __construct(
private string $name,
private int $price
) {}
public function getInfo(): string
{
return "{$this->name}:{$this->price}円";
}
}
src/Kamurocho/Weapon.php
<?php
namespace Kamurocho;
class Weapon
{
public function __construct(
private string $name,
private int $attack
) {}
public function getInfo(): string
{
return "{$this->name}(攻撃力: {$this->attack})";
}
}
alias_import.php
<?php
// Yakuza\Character と Kamurocho\Character が同名で衝突するため、
// use ... as でエイリアスを付けて両方を使用します
use Yakuza\Character as YakuzaCharacter;
use Kamurocho\Character as KamurochoCharacter;
// PHP 7以降: 同じ名前空間の複数クラスを {} でまとめてインポートできます
use Kamurocho\{Item, Weapon};
// それぞれのエイリアスでインスタンス化します
$kiryu = new YakuzaCharacter('桐生一馬', '東城会', 99);
$nishiki = new KamurochoCharacter('錦山彰', '東城会幹部');
$haruka = new KamurochoCharacter('遥', '桐生の義娘');
echo $kiryu->getProfile() . "\n";
echo $nishiki->describe() . "\n";
echo $haruka->describe() . "\n";
// まとめインポートしたクラスも通常通り使用できます
$item = new Item('タコヤキ', 500);
$weapon = new Weapon('木刀', 120);
echo $item->getInfo() . "\n";
echo $weapon->getInfo() . "\n";
実行すると次のように出力されます。
php alias_import.php 桐生一馬(東城会 / Lv.99) [神室町] 錦山彰(東城会幹部) [神室町] 遥(桐生の義娘) タコヤキ:500円 木刀(攻撃力: 120)
オートローディング(PSR-4(PHP Standards Recommendation 4 — PHP-FIGが策定したオートロード規約))との関係
composer.json
{
"autoload": {
"psr-4": {
"Yakuza\\": "src/Yakuza/",
"Kamurocho\\": "src/Kamurocho/"
}
}
}
autoload_example.php
<?php
// Composer のオートローダーを読み込みます
// これ以降、use で指定したクラスを require せずに自動で読み込めます
require_once __DIR__ . '/vendor/autoload.php';
use Yakuza\Character;
use Yakuza\Combat\Style;
// require_once を書かなくても、use で指定したクラスが自動で読み込まれます
// PSR-4 規約: 名前空間のセパレータ(\)がディレクトリ区切りに対応します
// Yakuza\Character → src/Yakuza/Character.php
// Yakuza\Combat\Style → src/Yakuza/Combat/Style.php
$kiryu = new Character('桐生一馬', '東城会', 99);
echo $kiryu->getProfile() . "\n";
echo Style::getDescription('legend') . "\n";
// グローバル名前空間のクラス(PHPビルトイン)は先頭に \ を付けます
// use がある名前空間ファイル内でも \Exception のように書けば確実です
try {
throw new \InvalidArgumentException('不正な引数です。');
} catch (\InvalidArgumentException $e) {
echo $e->getMessage() . "\n";
}
実行すると次のように出力されます。
php autoload_example.php 桐生一馬(東城会 / Lv.99) 龍のスタイル。圧倒的な威力を誇る究極スタイルです。 不正な引数です。
よくあるミス
よくあるミス1: namespaceの宣言位置ミス(<?phpより前にHTMLがある)
『namespace』は『<?php』の直後に記述する必要があります。それより前にHTMLや空白行があると致命的エラーになります。名前空間の宣言より前にはいかなる出力もできません。
ng_namespace_position.php
<!DOCTYPE html>
<html>
<?php
// HTMLの後にnamespaceを宣言しようとしています — これはエラーになります
namespace Yakuza;
class Character {}
実行すると次のように出力されます。
php ng_namespace_position.php Fatal error: Namespace declaration statement has to be the very first statement or after any declare call in the script
ok_namespace_position.php
<?php
// <?php の直後にnamespaceを記述します(これより前に何も書いてはいけません)
namespace Yakuza;
class Character
{
public function __construct(private string $name) {}
public function getName(): string
{
return $this->name;
}
}
実行すると次のように出力されます。
php ok_namespace_position.php
よくあるミス2: useとrequireの混同(useだけではファイルが読み込まれない)
『use』はクラスを短縮名で参照するための構文であり、ファイルを読み込む機能はありません。『require』や Composer のオートローダーと組み合わせて使用します。
ng_use_only.php
<?php
// useだけではファイルは読み込まれません
use Yakuza\Character;
// requireもオートローダーもないためクラスが見つからずエラーになります
$kiryu = new Character('桐生一馬', '東城会', 99);
echo $kiryu->getName() . "\n";
実行すると次のように出力されます。
php ng_use_only.php Fatal error: Class "Yakuza\Character" not found
ok_use_require.php
<?php
// requireでファイルを読み込んでからuseで短縮名を定義します
require_once __DIR__ . '/src/Yakuza/Character.php';
use Yakuza\Character;
$kiryu = new Character('桐生一馬', '東城会', 99);
echo $kiryu->getName() . "\n";
実行すると次のように出力されます。
php ok_use_require.php 桐生一馬
よくあるミス3: グローバルクラスの\忘れ(\Exceptionなど)
名前空間内のコードでは、PHPの組み込みクラス(『Exception』『InvalidArgumentException』など)の参照先が現在の名前空間として解釈されます。グローバル名前空間のクラスを参照するには先頭に『\』を付ける必要があります。
ng_global_class.php
<?php
namespace Yakuza;
// \を付けずにExceptionを使うと Yakuza\Exception を探してしまいます
try {
throw new Exception('エラーが発生しました。');
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
実行すると次のように出力されます。
php ng_global_class.php Fatal error: Class "Yakuza\Exception" not found
ok_global_class.php
<?php
namespace Yakuza;
// 先頭に \ を付けてグローバル名前空間のExceptionを参照します
try {
throw new \Exception('エラーが発生しました。');
} catch (\Exception $e) {
echo $e->getMessage() . "\n";
}
実行すると次のように出力されます。
php ok_global_class.php エラーが発生しました。
概要
『namespace』は同名のクラスや関数が衝突しないよう、コードをグループ化する仕組みです。Composerでサードパーティライブラリを使うと同名クラスが衝突しやすくなるため、自作コードには名前空間を付ける習慣が広く定着しています。名前空間の宣言は『<?php』の直後に1つだけ記述し、それより前にコード(HTMLも含む)を書いてはいけません。
『use』はインポートのための構文であり、ファイルを自動で読み込む機能はありません。ファイルの読み込みは別途『require』または Composer のオートローダーが担います。PSR-4(PHP Standards Recommendation 4 — PHP-FIGが策定したオートロード規約)に従って名前空間とディレクトリ構造を対応させることで、Composer が名前空間からファイルパスを自動解決し、『require』を一切書かずに済むようになります。
同名クラスが複数の名前空間に存在する場合は『use ... as エイリアス名』で区別します。また PHP 7 以降は同じ名前空間の複数クラスを『use 名前空間\{クラス1, クラス2}』とまとめて書けます。名前空間内からグローバルなビルトインクラスを使う際は先頭に『\』を付ける必要があります(例: 『\Exception』『\InvalidArgumentException』)。クラスの基本については『class』、ファイルの分割読み込みについては『include / require』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。