PHP 採用函式級作用域:函式內部預設無法存取外部變數,外部也無法直接存取函式內部變數。global 關鍵字建立「別名綁定」,讓函式內部變數指向全域符號表同一個 zval。
<?php
$globalVar = 'external';
function testGlobal() {
global $globalVar; // 宣告使用全域變數
echo $globalVar; // 輸出 external
$globalVar = 'modified';
}
testGlobal();
echo $globalVar; // 輸出 modified(外部變數被修改)
?>
<?php
function defineGlobal() {
global $newGlobal;
$newGlobal = 'created in function';
}
defineGlobal();
echo $newGlobal; // 輸出 created in function
?>
<?php
// A.php
function loadConfig() {
include 'config.php'; // 在函式內 include
// config.php 內的 $config 變成 loadConfig() 的區域變數!
}
loadConfig();
// 這裡無法存取 $config
?>
<?php
// config.php
$config = ['db' => 'localhost']; // 這裡的 $config 屬於 loadConfig() 區域作用域
?>
<?php
include 'config.php'; // 全域範圍 include
function loadConfig() {
global $config; // 明確宣告
// 使用 $config
}
?>
<?php
// config.php
return ['db' => 'localhost'];
// A.php
$config = include 'config.php'; // 取得回傳陣列
function loadConfig($config) {
// 參數傳遞,無作用域問題
}
?>
<?php
function setGlobal(&$var) {
$var = 'new value';
}
$value = 'old';
setGlobal($value);
echo $value; // new value
?>
<?php
$x = 1;
function test() {
$GLOBALS['x'] = 2; // 直接操作全域符號表
}
test();
echo $x; // 2
?>
$GLOBALS['var'] 不需宣告 global,語意清晰:明確存取全域。global $var 易被忽略、誤以為區域變數。$GLOBALS。| 場景 | 推薦做法 | 避免做法 |
|---|---|---|
| 函式需讀寫全域設定 | 參數傳遞 / 依賴注入容器 | global $config |
| 舊代碼快速修正 | $GLOBALS['key'] | global $key(易漏宣告) |
| include 設定檔 | return [...] + 變數接收 | 函式內 include |
| 單元測試 | 依賴注入,Mock 物件 | 依賴全域狀態 |
<?php
// 簡易容器範例
class Container {
private $services = [];
public function set($id, callable $factory) { $this->services[$id] = $factory; }
public function get($id) { return ($this->services[$id])($this); }
}
$container = new Container();
$container->set('config', fn() => include 'config.php');
$container->set('db', fn($c) => new PDO($c->get('config')['dsn'], ...));
// 使用
$db = $container->get('db');
?>
依賴注入(DI)讓相依關係顯性化、可測試、可替換,是現代 PHP 框架(Laravel、Symfony、Yii)的核心架構。