PHP - namespace の基本構文と宣言

PHP の名前空間(namespace)は、クラス名や関数名の衝突を防ぐための仕組みだ。大規模なプロジェクトや外部ライブラリを導入する場面では、同じ名前のクラスが複数存在することは珍しくない。名前空間を使えば、それぞれを別の空間に分離し、安全に共存させられる。

名前空間の宣言

名前空間は namespace キーワードで宣言する。ファイルの先頭(declare 文を除く)に記述しなければならず、それより前に HTML や echo などの出力があるとエラーになる。

<?php

namespace App\Models;

class User
{
    public string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }
}

この例では App\Models という名前空間の中に User クラスを定義している。外部からこのクラスを参照する場合、完全修飾名は App\Models\User となる。

名前空間がない場合の問題

名前空間を使わないとどうなるか。たとえば、自分のプロジェクトで Logger クラスを作り、外部ライブラリにも Logger クラスがあったとする。

名前空間なし

両方の Logger が同じグローバル空間に存在し、「Cannot declare class Logger, because the name is already in use」という致命的エラーが発生する

名前空間あり

App\LoggerVendor\Logger のように分離されるため、同名クラスが共存できる

このように名前空間は名前の衝突を根本的に解決する手段であり、現代の PHP 開発では必須の機能といえる。

宣言のルール

名前空間の宣言にはいくつかの制約がある。

ファイル先頭に書く

namespace 宣言より前にコードや出力があってはならない。唯一の例外は declare(strict_types=1) で、これだけは namespace より前に置ける。

1 ファイル 1 名前空間が原則

技術的には 1 ファイルに複数の名前空間を定義できるが、実務では 1 ファイルにつき 1 名前空間が標準的な慣習となっている。

declare 文との順序を具体的に見てみよう。

<?php

declare(strict_types=1);

namespace App\Services;

class PaymentService
{
    public function charge(int $amount): bool
    {
        return $amount > 0;
    }
}

declare(strict_types=1) は名前空間宣言の前に置く唯一の例外だ。この順序を逆にしてもエラーにはならないが、PSR-12 などのコーディング規約では上記の順序が推奨されている。

サブ名前空間

バックスラッシュ \ を使って階層構造を表現できる。これをサブ名前空間と呼ぶ。

<?php

namespace App\Http\Controllers;

class UserController
{
    public function index(): string
    {
        return 'User list';
    }
}

App\Http\Controllers は 3 階層の名前空間であり、ディレクトリ構造と対応させるのが一般的だ。PSR-4 オートローディング規約では、この名前空間が app/Http/Controllers/UserController.php というファイルパスに対応する。

名前空間を設計する

ディレクトリ構造を対応させる

PSR-4 でオートロードを設定する

この流れを守ることで、new App\Http\Controllers\UserController() と書くだけで PHP が自動的に正しいファイルを読み込んでくれる。

名前空間は「名前の整理」であり「実行時の分離」ではない

ここで一つ重要な点を押さえておきたい。PHP の名前空間は、あくまでクラス名・関数名・定数名を整理するための仕組みであり、実行時にメモリやスコープを分離する機能ではない。

PHP の namespace

名前(識別子)を論理的に分類する。実行時にはすべてのクラスが同じ空間にロードされ、完全修飾名で区別されるだけ

Java のパッケージや OS の namespace

アクセス制御やプロセス分離など、実行時のリソース隔離を伴う仕組み

たとえば App\Models\UserApp\Services\UserService は異なる名前空間に属しているが、実行時にはどちらも同じプロセス、同じメモリ空間で動作する。名前空間が違うからといってアクセスが制限されるわけではなく、完全修飾名さえ書けばどこからでも自由に参照できる。

<?php

namespace App\Services;

// 別の名前空間のクラスにも自由にアクセスできる
$user = new \App\Models\User('Alice');

名前空間に「遮断する壁」のようなイメージを持つと誤解が生じる。実態は、長い名前を省略して書くためのエイリアス機構に近いものだと考えるほうが正確だ。

グローバル名前空間

名前空間を宣言していないコードは、すべてグローバル名前空間に属する。名前空間の中からグローバル名前空間のクラスや関数を呼び出すには、先頭にバックスラッシュを付ける。

<?php

namespace App\Services;

class DateService
{
    public function now(): \DateTime
    {
        return new \DateTime();
    }
}

DateTime は PHP 組み込みのクラスでグローバル名前空間に存在する。名前空間内から参照する場合は \DateTime と書く必要がある。バックスラッシュを省略すると、PHP は App\Services\DateTime を探そうとしてエラーになる。

名前空間は PHP のコードを整理し、衝突のない安全な構造をもたらす基盤だ。次のステップとして use 文によるインポートを学べば、完全修飾名を省略してより簡潔なコードが書けるようになる。