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

开发轻量ORM时,如何让PDO Fetch Class返回分组集合对象?

实现分组集合对象的方案

当然可以搞定这个需求!这其实是主流ORM的常规操作——用一个集合类把查询出来的模型实例统一封装起来,既能像数组一样方便遍历,还能加一堆实用的操作方法。

1. 先写一个基础的Collection类

这个类要实现PHP的核心接口,让它能像数组一样被遍历、统计,同时封装常用的集合操作:

class Collection implements \IteratorAggregate, \Countable
{
    protected array $items = [];

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

    // 支持foreach遍历集合
    public function getIterator(): \Traversable
    {
        return new \ArrayIterator($this->items);
    }

    // 支持用count()统计集合元素数量
    public function count(): int
    {
        return count($this->items);
    }

    // 筛选符合条件的元素,返回新的Collection实例
    public function filter(callable $callback): self
    {
        return new static(array_filter($this->items, $callback));
    }

    // 对每个元素执行回调转换,返回新的Collection实例
    public function map(callable $callback): self
    {
        return new static(array_map($callback, $this->items));
    }

    // 获取指定索引的模型实例
    public function get(int $index): mixed
    {
        return $this->items[$index] ?? null;
    }

    // 获取集合中的第一个模型实例
    public function first(): mixed
    {
        return $this->items[0] ?? null;
    }

    // 把集合转换为关联数组(假设你的模型有toArray方法)
    public function toArray(): array
    {
        return array_map(fn($item) => $item->toArray(), $this->items);
    }
}

2. 修改基础模型的查询方法

把原来返回数组的逻辑改成返回Collection实例,统一封装查询结果:

abstract class BaseModel
{
    protected string $table;

    public static function all(): Collection
    {
        // 替换成你自己的数据库连接逻辑
        $pdo = new PDO('mysql:host=localhost;dbname=your_database', 'username', 'password');
        $stmt = $pdo->query("SELECT * FROM " . static::$table);
        
        // 用当前模型类实例化查询到的每一行数据
        $models = $stmt->fetchAll(PDO::FETCH_CLASS, static::class);
        
        // 把模型数组包装成Collection对象返回
        return new Collection($models);
    }
}

3. 实际使用效果

现在你的所有模型查询都会返回统一的集合对象,用法非常灵活:

// 获取所有问题的集合
$questions = Question::all();

// 直接遍历集合中的模型实例
foreach ($questions as $question) {
    echo "问题标题:{$question->title}\n";
}

// 统计集合总数
echo "共 " . count($questions) . " 个问题\n";

// 筛选出已发布的问题
$publishedQuestions = $questions->filter(fn($q) => $q->status === 'published');

// 获取第一个问题实例
$firstQuestion = $questions->first();

// 把集合转换为数组输出
print_r($publishedQuestions->toArray());

这么做的好处

  • 统一返回类型:不管查询结果是空、单条还是多条,都返回Collection,不用再写is_array()或者null判断的分支代码
  • 可扩展的操作:把筛选、排序、映射等常用操作封装在Collection里,代码更简洁优雅
  • 保留模型特性:集合里的每个元素都是完整的模型对象,能直接调用模型的方法和属性,不会丢失上下文

内容的提问来源于stack exchange,提问作者no.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:27:56