You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP OOP实现类Laravel Eloquent链式调用按需返回结果

类Laravel Eloquent链式调用实现方案

问题背景

我受Laravel Eloquent启发,正在编写一个简易的PHP数据库操作类,已知Laravel支持如下链式调用写法:

// 直接获取全量结果
$run = DB::table('users')->where('id', 3)->where('level', 2)->get();

// 获取结果后统计总数
$run = DB::table('users')->where('id', 3)->where('level', 2)->get()->count();

// 获取结果后取第一条
$run = DB::table('users')->where('id', 3)->where('level', 2)->get()->first();

// 获取结果后提取指定字段转数组
$run = DB::table('users')->where('id', 3)->where('level', 2)->get()->pluck('id')->toArray();

目前我已经实现了get()后接count()、first()的逻辑,但不知道怎么让get()直接调用时返回全量结果,最初设想是类似如下的分支判断逻辑:

function __construct() {
   if(当get()之后没有接续调用其他方法时){
      // 返回默认结果集
      return $this->results();
   }
   else{
      // 执行后续链式调用逻辑
   }
}

核心实现原理

首先要明确一个认知:PHP执行代码是从左到右逐段解析的,调用get()的瞬间,PHP根本不知道后面会不会接续调用其他方法,你伪代码里写的「判断get()后有没有后续调用」的逻辑在PHP层面根本无法实现。

Laravel的链式调用从来不是在同一个类里做分支判断,核心逻辑是不同阶段返回不同类的实例:

  • 调用table()/from()/where()这类拼接查询条件的方法时,返回「查询构造器类」自身的实例,所以可以持续拼接查询条件
  • 调用get()方法时,不直接返回原生数组结果,而是返回一个集合(Collection)类实例,所有对结果集的操作(count、first、pluck等)都封装在集合类中
  • 集合类的方法如果是对结果集做加工,就返回加工后的新集合实例,继续支持链式调用;如果是输出最终值(比如count()返回数字、toArray()返回原生数组),链式调用自然终止。

补充说明:你猜测的->get()->pluck('id')->toArray()->first()写法在Laravel中实际会报错,toArray()返回的是原生PHP数组,不存在可调用的first()方法,只有集合实例才能调用集合封装的方法。

具体实现代码

你只需要把查询构造逻辑和结果处理逻辑拆成两个独立的类,就能兼容所有调用场景:

1. 查询构造器类(即你当前编写的DB类)

所有拼接SQL的方法执行完逻辑后返回$this支持链式拼接,get()方法执行SQL拿到结果集后,不直接返回数组,而是返回集合类实例:

class DB
{
    protected $table;
    protected $wheres = [];

    public static function from(string $table): self
    {
        $instance = new self();
        $instance->table = $table;
        return $instance;
    }

    public function where(string $column, $value): self
    {
        $this->wheres[] = [$column, '=', $value];
        return $this;
    }

    public function get(): Collection
    {
        // 这里替换成你实际执行SQL、拿到结果集数组的逻辑
        $results = $this->executeQuery(); 
        // 返回集合实例,而不是原生数组
        return new Collection($results);
    }

    // 你的实际SQL执行逻辑
    protected function executeQuery(): array
    {
        // 省略SQL拼接、PDO查询逻辑,最终返回查询到的二维数组
        return [];
    }
}

2. 集合类(封装结果集操作)

构造方法接收查询到的结果数组,所有结果处理方法都在这个类中实现:

class Collection
{
    protected $items = [];

    public function __construct(array $items)
    {
        $this->items = $items;
    }

    // 返回结果总数
    public function count(): int
    {
        return count($this->items);
    }

    // 返回第一条结果
    public function first()
    {
        return $this->items[0] ?? null;
    }

    // 提取指定字段,返回新集合实例支持继续链式
    public function pluck(string $column): self
    {
        $plucked = array_column($this->items, $column);
        return new self($plucked);
    }

    // 返回原生数组结果
    public function toArray(): array
    {
        return $this->items;
    }
}

适配直接调用get()的场景

如果你需要get()返回的集合实例可以直接像数组一样遍历、或者直接输出转JSON,可以给Collection类实现PHP内置的预置接口:

// 实现IteratorAggregate接口支持遍历,实现JsonSerializable接口支持JSON序列化
class Collection implements \IteratorAggregate, \JsonSerializable
{
    // ... 原有代码不变

    public function getIterator()
    {
        return new \ArrayIterator($this->items);
    }

    public function jsonSerialize()
    {
        return $this->items;
    }
}

实现后你可以直接遍历get()返回的结果,和使用原生数组体验完全一致。

内容的提问来源于stack exchange,提问作者WEB TM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 18:18:38