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

PHP 5.3 新魔術方法 __invoke 詳解:讓對象像函數一樣可調用

     編輯:PHP 相關知識

PHP 5.3 新魔術方法 __invoke 詳解:讓對象像函數一樣可調用

PHP 5.3 引入 __invoke() 魔術方法,標誌著 PHP 邁向「可調用對象」編程範式。本文詳細解析 __invoke 的語法、調用規則、is_callable 判斷、實戰場景(策略模式、中間件、閉包替代),並附帶完整魔術方法速查表。

基礎語法與演示

<?php
class Greeter
{
    public function __construct(private string $prefix = 'Hello') {}

    public function __invoke(string $name): string
    {
        return "{$this->prefix}, {$name}!";
    }
}

$greeter = new Greeter('Hi');
echo $greeter('World');        // Hi, World!
echo $greeter('PHP');          // Hi, PHP!

// 判斷可調用性
var_dump(is_callable($greeter)); // true
var_dump(is_callable([$greeter, '__invoke'])); // true
?>

官方示例解析

<?php
class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}

$obj = new CallableClass;
$obj(5);                       // int(5)
var_dump(is_callable($obj));   // bool(true)
?>

核心特性

  1. 調用語法糖:$obj($arg) 等價於 $obj->__invoke($arg)。
  2. 參數/返回值無限制:支持類型聲明、可變參數、引用傳遞、返回類型聲明(PHP 7.0+)。
  3. 繼承鏈查找:子類未定義 __invoke 時會向父類查找,同 __call。
  4. 可作為回調傳遞:array_map($greeter, ['A','B'])、usort($arr, new Comparator)。

實戰場景:策略模式無需介面

<?php
// 策略對象
class JsonEncoder { public function __invoke($data) { return json_encode($data, JSON_UNESCAPED_UNICODE); } }
class XmlEncoder  { public function __invoke($data) { /* ... */ } }

// 上下文
class Exporter
{
    public function __construct(private $encoder) {}

    public function export(array $data): string
    {
        return ($this->encoder)($data); // 直接調用策略對象
    }
}

$exporter = new Exporter(new JsonEncoder());
echo $exporter->export(['status' => 'ok']); // {"status":"ok"}
?>

實戰場景:PSR-15 中間件鏈

<?php
interface MiddlewareInterface
{
    public function __invoke(Request $request, callable $next): Response;
}

class AuthMiddleware implements MiddlewareInterface
{
    public function __invoke(Request $request, callable $next): Response
    {
        if (!$request->hasHeader('Authorization')) {
            return new Response(401, [], 'Unauthorized');
        }
        return $next($request);
    }
}

// 構建鏈
$chain = [
    new AuthMiddleware(),
    new RateLimitMiddleware(),
    fn($req) => new Response(200, [], 'OK'),
];

$dispatch = function (Request $req) use ($chain) {
    $next = array_shift($chain);
    return $next($req, $dispatch);
};
?>

PHP 所有魔術方法速查表

方法觸發時機典型用途
__construct實例化 new Class()依賴注入、屬性初始化
__destruct對象銷毀(GC/腳本結束)釋放資源、關閉連接、寫入日誌
__call調用不可訪問實例方法代理、動態方法、流式接口
__callStatic調用不可訪問靜態方法靜態工廠、ActiveRecord 查詢
__get讀取不可訪問屬性虛擬屬性、懶加載、數組訪問
__set寫入不可訪問屬性屬性驗證、觸發事件、脏標記
__issetisset($obj->prop)虛擬屬性存在性判斷
__unsetunset($obj->prop)清理虛擬屬性
__sleepserialize($obj)指定序列化屬性、關閉資源
__wakeupunserialize($str)重建連接、初始化資源
__serializePHP 7.4+ serialize()精確控制序列化數據結構
__unserializePHP 7.4+ unserialize()精確控制反序列化邏輯
__toString對象作字符串使用 echo $obj調試輸出、模板渲染、ID 展示
__invoke$obj()可調用對象、策略、中間件、閉包替代
__set_statevar_export() 導出自定義導出結構
__cloneclone $obj深拷貝、重置 ID、復制關聯對象
__debugInfovar_dump($obj) (PHP 5.6+)隱藏敏感屬性、格式化調試輸出

避坑指南

  • __autoload 已棄用(PHP 7.2 移除),請使用 spl_autoload_register。
  • __wakeup 中拋出的異常 無法被 catch 捕獲,會導致致命錯誤,請內部 try-catch 處理。
  • __toString 拋出異常會觸發 E_RECOVERABLE_ERROR,PHP 7.4+ 允許拋出 Throwable。
  • 魔術方法 必須聲明為 public,否則不會被觸發。

__invoke 讓 PHP 對象具備了一級函數特性,是函數式編程風格在 PHP 中落地的關鍵基礎設施。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved