global?global 關鍵字會建立隱性耦合,導致:
<?php
$db = new PDO($dsn, $user, $pass);
$settings = new Settings();
$user = new User();
function process($db, $settings, $user) { /* ... */ }
process($db, $settings, $user);
✅ 明確依賴、易測試。❌ 參數過多時呼叫繁瑣、新增依賴需改所有簽名。
<?php
class DBConnection {
private static $instance;
private function __construct() {}
public static function getInstance(): self {
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
// 使用
$db = DBConnection::getInstance();
✅ 全域存取點單一。❌ 隱性依賴、難以 Mock、無法多實例、違反單一職責。
中央容器管理所有共享物件,依賴明確、支援多實例、易測試、易擴展。
<?php
/**
* 登記器:中央物件容器
*/
class Registry {
private static $instance;
private $objects = [];
private function __construct() {}
public static function getInstance(): self {
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function set(string $name, $object): void {
$this->objects[$name] = $object;
}
public function get(string $name) {
return $this->objects[$name] ?? null;
}
public function has(string $name): bool {
return isset($this->objects[$name]);
}
public function remove(string $name): void {
unset($this->objects[$name]);
}
}
// === 應用啟動時註冊 ===
$registry = Registry::getInstance();
$registry->set('db', new PDO($dsn, $user, $pass));
$registry->set('config', new Config('config.ini'));
$registry->set('user', User::fromSession());
$registry->set('logger', new Logger('/var/log/app.log'));
// === 任何處取用 ===
function handleRequest() {
$registry = Registry::getInstance();
$db = $registry->get('db');
$user = $registry->get('user');
$logger = $registry->get('logger');
$logger->info('Processing request for ' . $user->name);
// ...
}
<?php
// 使用 league/container 或 php-di/php-di
require 'vendor/autoload.php';
use League\Container\Container;
$container = new Container();
// 註冊共享實例
$container->addShared('db', function() {
return new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
});
$container->addShared('config', function() {
return parse_ini_file('config.ini', true);
});
// 註冊工廠(每次新實例)
$container->add('form_validator', function() {
return new FormValidator();
});
// 取用
$db = $container->get('db');
$validator = $container->get('form_validator');
<?php
class Request {
private $data;
public function __construct() {
$this->data = [
'get' => $_GET,
'post' => $_POST,
'cookie' => $_COOKIE,
'server' => $_SERVER,
'files' => $_FILES,
];
}
public function get(string $key, $default = null, string $source = 'post') {
$source = strtolower($source);
return $this->data[$source][$key] ?? $default;
}
public function all(string $source = 'post'): array {
return $this->data[strtolower($source)] ?? [];
}
public function input(string $key, $default = null) {
// 依序檢查 POST > GET > COOKIE
foreach (['post', 'get', 'cookie'] as $source) {
if (isset($this->data[$source][$key])) {
return $this->data[$source][$key];
}
}
return $default;
}
}
// 註冊到 Registry
Registry::getInstance()->set('request', new Request());
// 使用
$request = Registry::getInstance()->get('request');
$name = $request->input('name'); // 自動從 POST/GET/COOKIE 取值
$email = $request->get('email', '', 'post'); // 強制從 POST 取
| 框架 | 容器實作 | 取用方式 |
|---|---|---|
| Laravel | Illuminate\Container | app('db'), resolve(User::class) |
| Symfony | DependencyInjection | 服務自動注入、$this->get('service') |
| CodeIgniter 4 | CodeIgniter\Services | service('db'), model('UserModel') |
| Yii 2 | yii\di\Container | Yii::$container->get() |
| Slim 4 | PHP-DI / League\Container | 建構子注入、$container->get() |
global 關鍵字(除非極少數 legacy 維護)。