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

PHP __call 魔術方法實現動態連貫操作:數據庫查詢建構器

     編輯:PHP 相關知識

PHP __call 魔術方法實現動態連貫操作

利用 __call($method, $args) 攔截不存在的方法調用,將方法名映射為 SQL 子句鍵名,參數存入屬性,返回 $this 實現鏈式調用。比顯式定義每個方法更靈活,易於擴展。

動態建構器核心代碼

class DbBuilder {
    // 定義支援的鏈式方法 (對應 SQL 子句)
    protected $clauses = [
        'field'  => '',
        'where'  => '',
        'order'  => '',
        'limit'  => '',
        'group'  => '',
        'having' => '',
    ];

    public function __call(string $method, array $args) {
        $method = strtolower($method);
        if (isset($this->clauses[$method])) {
            $this->clauses[$method] = $args[0] ?? '';
            return $this;
        }
        throw new BadMethodCallException("未支援的方法: $method");
    }

    public function select(): string {
        $sql = "SELECT {$this->clauses['field']} FROM `test` ";
        $sql .= "{$this->clauses['where']} ";
        $sql .= "{$this->clauses['group']} ";
        $sql .= "{$this->clauses['having']} ";
        $sql .= "{$this->clauses['order']} ";
        $sql .= "{$this->clauses['limit']}";
        return trim(preg_replace('/\s+/', ' ', $sql));
    }
}

// 使用
$db = new DbBuilder();
echo $db->field('name, sex, address')
        ->where('name = "gongwen"')
        ->limit('1')
        ->select();
// SELECT name, sex, address FROM `test` WHERE name = "gongwen" LIMIT 1

優化點

  1. 白名單校驗:isset($this->clauses[$method]) 防止任意屬性寫入。
  2. 參數標準化:$args[0] ?? '' 兼容無參調用。
  3. SQL 注入風險:此處為演示直接拼接,**生產必須用參數綁定** (見上一篇)。
  4. 可擴展性:新增 'join' => '' 即支援 ->join('...'),無需新增方法。

對比:顯式方法 vs __call

維度顯式方法__call 動態
代碼量多 (每個子句一個方法)少 (統一攔截)
IDE 提示完美支援無 (需 @method 註解)
擴展新子句新增方法修改白名單陣列
參數驗證/轉換靈活 (每個方法獨立)統一處理 (需額外邏輯)
效能極快 (直接調用)微弱開銷 (魔術方法查找)

實戰建議

  • 核心高頻方法 (where, order, limit) 用顯式定義,獲得 IDE 提示與參數驗證。
  • 低頻/擴展子句 (partition, window, hint) 用 __call 動態支援。
  • 配合 @method 註解讓 PHPStorm 識別動態方法:@method self where(string $cond)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved