首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 變數作用域、引用、物件傳遞與複製完整指南

     編輯:PHP 相關知識

變數作用域規則

範圍說明範例
全域腳本最外層、include/require 引入檔案$a = 1; include 'b.inc'; // $a 在 b.inc 可見
區域 (函數內)函數內部預設為區域作用域function test() { echo $a; } // 無輸出,區域 $a 未定義
靜態函數內 static $var,跨呼叫保持值function c() { static $i=0; echo $i++; }
超全域$GLOBALS, $_GET, $_POST, $_SESSION... 所有範圍可見function f() { echo $GLOBALS['x']; }

global vs $GLOBALS 差異回顧

<?php
$x = 1;
function test_global() {
    global $x;        // 建立區域別名指向全域 $x
    $x = 2;
}
function test_globals() {
    $GLOBALS['x'] = 3; // 直接操作超全域陣列
}
test_global();  // 全域 $x 變為 2
test_globals(); // 全域 $x 變為 3

// unset 差異
function unset_global() {
    global $x;
    unset($x);        // 僅銷毀區域別名
}
function unset_globals() {
    unset($GLOBALS['x']); // 真正銷毀全域變數
}
?>

變數引用機制

基本引用指派

<?php
$a = 'ABC';
$b = &$a;  // $b 成為 $a 的別名
$b = 'EFG';
echo $a; // EFG(同一記憶體)

// 函數參數傳址
function add100(&$n) { $n += 100; }
$val = 1;
add100($val);
echo $val; // 101

// 函數回傳引用
function &getRef() {
    static $v = 0;
    return $v;
}
$r = &getRef();
$r = 5; // 修改靜態變數
echo getRef(); // 5
?>

引用計數與 Copy-on-Write (COW)

<?php
$a = 'ABC';  // 記憶體:'ABC' (refcount=1)
$b = $a;     // 記憶體:'ABC' (refcount=2) - 共享
$a = 'EFG';  // 觸發 COW:複製 'ABC' 給 $b,$a 指向新 'EFG'
// 現在:$a='EFG', $b='ABC',各自獨立記憶體
?>

物件傳遞行為 (PHP 5+)

預設為「傳遞物件識別符」

<?php
class A { public $val = 'ABC'; }
$obj1 = new A();
$obj2 = $obj1;      // 複製識別符,指向同一物件
$obj3 = &$obj1;     // 別名,效果相同
$obj4 = clone $obj1; // 深複製,建立新物件

$obj1->val = 'DEF';
echo $obj2->val; // DEF(同一物件)
echo $obj4->val; // ABC(獨立副本)

__clone() 魔術方法自訂複製行為

<?php
class User {
    public $name;
    private $createdAt;
    private $dbConnection; // 不可序列化資源
    
    public function __construct($name) {
        $this->name = $name;
        $this->createdAt = new DateTime();
        $this->dbConnection = new PDO(...);
    }
    
    public function __clone() {
        // 深複製日期物件
        $this->createdAt = clone $this->createdAt;
        // 重新建立資料庫連線
        $this->dbConnection = new PDO(...);
        // 或設為 null 稍後懶載入
    }
}
$u1 = new User('Alice');
$u2 = clone $u1; // 自動呼叫 __clone()

取消引用與記憶體管理

<?php
$a = 1;
$b = &$a;
unset($a);  // 僅移除 $a 符號,$b 仍保留值 1
var_dump($b); // int(1)

// 循環引用記憶體洩漏範例(PHP 5.3+ 有 GC 可回收)
class Node {
    public $parent;
    public $children = [];
}
$parent = new Node();
$child = new Node();
$parent->children[] = $child;
$child->parent = $parent; // 循環引用
unset($parent, $child);   // PHP 5.3+ 會自動回收,舊版本會洩漏

最佳實踐總結

  1. 函數參數:預設傳值(COW 效能佳),大型陣列/需修改原值時用 &$param
  2. 物件:預設傳遞識別符(類似引用),需獨立副本用 clone
  3. 全域變數:避免使用,改用依賴注入或單例模式
  4. 靜態變數:函數內 static 保持狀態,類別屬性用 static 共享
  5. 記憶體優化:大型資料處理完畢及時 unset(),必要時 gc_collect_cycles()
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved