單例模式確保類全局僅有一實例,並提供訪問點。PHP 中主要用於資料庫連接、配置管理、日誌服務等資源密集型對象。本文給出生產級標準實現,含防克隆、防序列化、延遲初始化、線程安全 (Swoole 環境) 等完善細節。
new Class()。getInstance() 延遲初始化並返回實例。final class Database {
private static ?self $instance = null;
private PDO $pdo;
// 防止外部實例化
private function __construct() {
$this->pdo = new PDO(
"mysql:host=localhost;dbname=test;charset=utf8mb4",
'user', 'pass',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
}
// 防止克隆
private function __clone() {}
// 防止反序列化
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 代理 PDO 方法
public function __call(string $method, array $args) {
return $this->pdo->$method(...$args);
}
}
// 使用
$db = Database::getInstance();
$stmt = $db->query("SELECT * FROM users");
Swoole Worker 進程間內存隔離,單例需配合進程 ID 或共享內存:
class Singleton {
private static array $instances = [];
public static function getInstance(): self {
$pid = getmypid(); // 或 Swoole\Process::getPid()
if (!isset(self::$instances[$pid])) {
self::$instances[$pid] = new self();
}
return self::$instances[$pid];
}
}
// AppServiceProvider::register()
$this->app->singleton(Database::class, function ($app) {
return new Database(
$app['config']['database.connections.mysql']
);
});
// 控制器自動注入
public function index(Database $db) { ... }
容器管理生命周期,比手寫單例更靈活、可測試。
單例是「全局唯一訪問點」而非「全局變量」,克制使用、封裝內部狀態、配合容器管理,才是成熟架構的表現。