val/one-to-many-iterator

一对一连接的辅助迭代器和生成器

v1.0.1 2015-03-02 13:59 UTC

This package is not auto-updated.

Last update: 2024-09-24 08:28:06 UTC


README

一对一连接的辅助迭代器和生成器。

概述

当你想要获取一对一关系时,你可能使用 JOIN 来避免 N+1 查询问题

尽管如此,迭代结果可能很困难,尤其是在你需要为某个过程加载关系的整个“多”部分时。

这就是我创建这个小型库的原因。它接受一个数组的 Traversable,有一个共同的键来区分一对一关系的“一”部分,并按此键排序(因此可以流式传输项目,而无需在内存中加载整个集合)。

然后它将关系的“多”部分聚合到一个可配置的键中。

安装

composer require val/one-to-many-iterator

示例

你的数据库结果迭代器,一旦转换为数组,看起来像这样(一个典型的 JOIN

<?php

[
    ['id' => 1, 'parent_column' => 'hello', 'child_column' => 'foo'],
    ['id' => 1, 'parent_column' => 'hello', 'child_column' => 'bar'],
    ['id' => 2, 'parent_column' => 'world', 'child_column' => 'baz'],
];

但你想迭代类似这样的内容

<?php

[
    [
        'id' => 1,
        'parent_column' => 'hello',
        'children' => [
            ['child_column' => 'foo'],
            ['child_column' => 'bar'],
        ],
    ],
    [
        'id' => 2,
        'parent_column' => 'world',
        'children' => [
            ['child_column' => 'baz'],
        ],
    ],
];

为了实现这一点,只需将你的数据库结果传递给 Val\Iterator\OneToManyIteratorVal\Iterator\OneToManyGenerator,同时配置共同的键(这里,id),以及聚合键(这里,children)。

假设 $result 包含原始 SQL 结果迭代器

<?php

// With an iterator
$aggregated = new OneToManyIterator('id', 'children', $result);

// With a generator
$aggregated = new OneToManyGenerator('id', 'children', $result);

foreach ($aggregated as $i => $parent) {
    $parent['id'];
    $parent['parent_column'];

    foreach ($parent['children'] as $child) {
        $child['child_column'];
    }
}

迭代器和生成器之间的区别在于,前者实现了一个原始的 PHP 迭代器,而后者使用了一个 PHP 生成器(自 5.5 版本以来可用)。

错误

  • 当使用 LEFT JOIN 而不是 JOIN 时,因此不能保证至少有一个关系项的存在,聚合字段仍然会包含一个值为 null 的项。