ど素人から毛を生やす。<延>

[PHP]名前空間で自動インクルードする という幻想

Web > PHP 2026年10月6日(最終更新:8日前)

どもです。
自分はPHPというものに関わってきて既にウン年…ちょっと数えるのも躊躇う年月が経っていますが、やってきた仕事の都合上、名前空間というものを自分で使うことなく、なんとなくの理解でやり過ごしてきました。

が、どうやら直視せねばならない時がやってきたようです。
しかし自分のような「PHPはまあ充分理解しているといっても過言じゃないが、名前空間のことはほぼさっぱり分からん」という輩向けの解説というものは存在しないものです。

今回はそういう話です。

名前空間 とは、自動でクラスをインクルードしてくれる機能である??

取り敢えずGeminiに「PHP分かる人に対して名前空間を説明してみせい」と言ってみました。

//自分は「doshirouto」フォルダにいるという宣言
namespace doshirouto;

//「core\Logger」のショートカットを作る
use core\Logger; 

class Main{
    public function create() {
        $logger = new Logger();
    }
}

はい。もう匙を投げました。

「core\Logger」のショートカットを作る

意味が分かりません。ルートはどこなんですか。Loggerはフォルダ名ですか、ファイル名ですか。

名前空間のルートやルールは、vendor/autoload.phpが決める???

どうやら、名前空間のことになると、なぜかComposer(PHPのパッケージ管理システム)ありきの話になりがちなようです。

プロジェクト/
├── vendor/         Composerが管理する外部ライブラリ
├── composer.json   名前空間とフォルダの紐付けを設定するファイル
└── src/            自分で書くのはこの中身
    ├── doshirouto/
    │   └── Main.php
    └── core/
        └── Logger.php

Composerを使うと、プロジェクトのフォルダ構成はこうなります。

composer dump-autoload コマンドを実行することで、vendorにautoload.phpが生成されます。

このファイルの中身は、composer.jsonに従って生成されたリンク群であり、使おうとしたクラスが見つからない場合に autoload.php の中身が実行され、autoload.php にてインクルードが行われます。

このとき、autoload.php のルールで、namespace のルートは src ディレクトリにされます。

つまり、名前空間を使えば一定ルールでファイルが自動インクルードされる、というのは、
×名前空間の機能
○Composerが名前空間を利用して勝手に実装した機能
だということ。

どうやら、自分は根本的な思い違いをしていたようです。

本当の namespace

さて、自分はnamespaceを勘違い、というか過大評価していたようです。
本当のnamespaceを理解する必要があります。

namespace doshirouto; //このファイルは「doshirouto」という名前空間下にいるという宣言

function exec(){}

というファイルがあった場合に、

require_once 'さっきのやつ.php';

doshirouto\exec(); //「doshirouto」という名前空間下のexec()を実行する

とすることで、プロジェクト内にexec()がいくつあっても関数名重複にならない。
これが名前空間の本来の用途のようです。

また、実用では名前空間は多階層化する宿命にあります。

doshirouto\product\item\test\exec(); //「doshirouto」下の「product」下の「item」下の「test」下のexec()を実行する

こんな呼び出し方をするのは御免なので、useを使います。

use doshirouto\product\item\test; //「doshirouto」下の「product」下の「item」下の「test」を、このファイルでは「test」として扱う指定

test\exec() //「test」下のexec()を実行する

これがuseの本来の用途。
なんでこれが自動インクルードなんかに飛躍してしまったんだ…?

使おうとしたクラスが見つからない場合のPHP機能 spl_autoload_register

spl_autoload_register('AAA::bbb')

と記載しておくと、使おうとしたクラスが見つからない場合に「AAAクラスのbbb関数」を呼び出します。

function bbb($className){}

呼び出した関数には、使おうとしたクラス名が第一引数にセットされます。
そして、この引数に入る値には、名前空間が適用されます。useを使っていた場合、ちゃんとnamespaceのパスに置き換えられます。

つまり…

名前空間で自動インクルードする という幻想の正体

spl_autoload_register('AAA::bbb');
class AAA{
	function bbb($className){
		$className = str_replace('\\', '/', $className); //名前空間のセパレータは「\」なので、インクルード用の「/」に変換する
		require_once($className.'.php');
	}
}

辿り着きました。
これが「名前空間で自動インクルードする」という幻想の正体です。

ここでは超最低限の記載にしていますが、spl_autoload_register で指定した関数の書き方は基本的に自由です。
autoload.php のように膨大なリスト形式にしても良し、自動でアドレスを生成しても良し、勝手にルートを設定しても良しです。

おまけ \Exception の話

最近の解説サイトでは、try-catchを行うときに、だいたいこう書かれています。

catch(\Exception $e){
	...
}

この\Exceptionの「\」の意味が分かっていなかったのですが、これ調べてる最中のついでに理解しました。
名前空間を使わないプロジェクトでは、あっても無くても同じだったので。

名前空間下にで宣言する場合、PHP標準クラス(ThrowableとかDateTimeとか)は「\」をつけないと、自分の名前空間内の関数を探しに行ってしまうからだそう。

namespace doshirouto;

new Exception();

だと、doshirouto\Exceptionを参照しようとしてしまうという。

ほーん。そういう。


参考サイト:
【PHP超入門】名前空間(namespace・use)について

Composerに汚染されていない名前空間の学習がしたいならここ。

この記事は役に立ちましたか?
  • _(:3」∠)_ 面白かった (0)
  • (・∀・) 参考になった (0)
  • (`・ω・´) 役に立った (0)