PHP 命名空間 (Namespace)

命名空間用來組織程式碼,避免類別、函數和常數的名稱衝突。當你的專案規模成長,或引入第三方套件時,很可能會遇到不同來源的類別有相同名稱的問題(例如兩個套件都有 User 類別)。命名空間讓你可以將程式碼分組,就像檔案系統中的資料夾一樣,確保即使名稱相同也不會衝突。

定義命名空間

使用 namespace 關鍵字定義命名空間。它必須是檔案中的第一行 PHP 程式碼(在 <?php 之後,任何其他程式碼之前)。

<?php
// File: src/Models/User.php
namespace App\Models;

class User {
    public function __construct(
        public string $name
    ) {}
}
?>
<?php
// File: src/Controllers/UserController.php
namespace App\Controllers;

class User {  // 不會和 App\Models\User 衝突
    public function index(): void {
        echo "User Controller";
    }
}
?>

使用命名空間

有三種方式可以引用命名空間中的類別:

完整名稱

使用完整的命名空間路徑(以 \ 開頭表示從全域開始):

<?php
$user = new \App\Models\User("Alice");
?>

use 語句

使用 use 語句匯入類別,之後可以直接使用類別名稱:

<?php
use App\Models\User;

$user = new User("Alice");
?>

別名

當需要使用相同名稱的多個類別時,可以用 as 指定別名:

<?php
use App\Models\User as UserModel;
use App\Controllers\User as UserController;

$model = new UserModel("Alice");
$controller = new UserController();
?>

群組匯入

<?php
// 群組匯入相同命名空間的類別
use App\Models\{User, Post, Comment};

// 或
use App\Models\User;
use App\Models\Post;
use App\Models\Comment;
?>

函數和常數

<?php
namespace App\Utils;

const VERSION = '1.0.0';

function helper(): string {
    return "Helper function";
}

class Utility {
    public static function format(): string {
        return "Formatted";
    }
}
?>
<?php
use App\Utils\Utility;
use function App\Utils\helper;
use const App\Utils\VERSION;

echo VERSION;        // 1.0.0
echo helper();       // Helper function
echo Utility::format();
?>

全域命名空間

PHP 內建的類別和函數(如 DateTimeExceptiondate() 等)都在全域命名空間中。當你在一個有命名空間的檔案中使用它們時,需要加上前綴 \ 來明確指定是全域命名空間:

<?php
namespace App\Services;

class DateService {
    public function now(): \DateTime {
        return new \DateTime();  // PHP 內建類別
    }
    
    public function format(): string {
        return \date('Y-m-d');  // PHP 內建函數
    }
}
?>

命名空間慣例

PSR-4 自動載入標準:

App\                    → src/
App\Models\User         → src/Models/User.php
App\Controllers\Home    → src/Controllers/Home.php

實際範例

<?php
// src/Models/User.php
namespace App\Models;

class User {
    public function __construct(
        public int $id,
        public string $name,
        public string $email
    ) {}
}
?>
<?php
// src/Repositories/UserRepository.php
namespace App\Repositories;

use App\Models\User;

class UserRepository {
    private array $users = [];
    
    public function find(int $id): ?User {
        return $this->users[$id] ?? null;
    }
    
    public function save(User $user): void {
        $this->users[$user->id] = $user;
    }
}
?>
<?php
// src/Services/UserService.php
namespace App\Services;

use App\Models\User;
use App\Repositories\UserRepository;

class UserService {
    public function __construct(
        private UserRepository $repository
    ) {}
    
    public function createUser(string $name, string $email): User {
        $user = new User(
            id: random_int(1, 1000),
            name: $name,
            email: $email
        );
        
        $this->repository->save($user);
        return $user;
    }
}
?>