PHP 5/7/8 逐步完善了物件模型。本文系統講解五大進階特性,附帶可運行的完整代碼示例,助你寫出更健壯、可維護的代碼。
PHP 通過魔術方法實現「屬性/方法不存在時的攔截」,官方稱為重載(與 Java/C++ 語義不同)。
<?php
class DynamicEntity {
private $data = [];
// 寫入不可見屬性
public function __set(string $name, $value) {
echo "__set $name = $value\n";
$this->data[$name] = $value;
}
// 讀取不可見屬性
public function __get(string $name) {
echo "__get $name\n";
return $this->data[$name] ?? null;
}
// 檢測 isset/empty
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
// unset()
public function __unset(string $name) {
unset($this->data[$name]);
}
// 調用不可見實例方法
public function __call(string $name, array $args) {
echo "__call $name(" . implode(', ', $args) . ")\n";
}
// 調用不可見靜態方法
public static function __callStatic(string $name, array $args) {
echo "__callStatic $name(" . implode(', ', $args) . ")\n";
}
}
$obj = new DynamicEntity();
$obj->foo = 'bar'; // 觸發 __set
echo $obj->foo; // 觸發 __get
$obj->dynamicMethod(1,2); // 觸發 __call
DynamicEntity::staticCall('x'); // 觸發 __callStatic
class Prototype {
public $primitive = 'value';
public $objectRef;
public function __construct() { $this->objectRef = new stdClass(); }
// 克隆鉤子:執行深拷貝邏輯
public function __clone() {
$this->objectRef = clone $this->objectRef; // 遞歸深拷貝引用屬性
}
}
$a = new Prototype();
$b = clone $a; // 觸發 __clone
var_dump($a === $b); // false (不同實例)
var_dump($a == $b); // true (屬性值相等)
var_dump($a->objectRef === $b->objectRef); // false (深拷貝後引用不同)
規則:== 比較屬性值;=== 比較是否同一實例;clone 默認淺拷貝,引用類型需在 __clone 中手動深拷貝。
| 語句 | 找不到文件 | 重複引入 |
|---|---|---|
include | Warning,繼續 | 多次執行 |
require | Fatal Error,終止 | 多次執行 |
include_once | Warning | 僅一次 |
require_once | Fatal Error | 僅一次 |
PSR-4 自動加載(現代標準):
// composer.json
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
// 執行 composer dump-autoload 後,直接使用
use App\Models\User;
$user = new User(); // 自動載入 src/Models/User.php
舊式 __autoload(已棄用,PHP 8.0 移除):
function __autoload($class) {
require_once __DIR__ . "/$class.class.php";
}
<?php
namespace MyProject\Components;
const VERSION = '1.0';
function helper() { echo "helper\n"; }
class Tool { public function run() { echo "running\n"; } }
// 子命名空間
namespace MyProject\Components\Utils;
const DEBUG = true;
// 使用方式
namespace AnotherProject;
use MyProject\Components as C;
use MyProject\Components\Utils;
use function MyProject\Components\helper;
use const MyProject\Components\VERSION;
echo C\VERSION; // 1.0
helper(); // helper
$t = new C\Tool(); // 實例化
$t->run();
關鍵字:namespace 定義、`use` 導入/別名、`__NAMESPACE__` 常量、`\` 全限定名前綴。
declare(strict_types=1);private string $name;readonly class (PHP 8.1+) 或 private set。__autoload。