【问题标题】:Convert Zend\Db\ResultSet\HydratingResultSet to Array of Objects将 Zend\Db\ResultSet\HydratingResultSet 转换为对象数组
【发布时间】:2013-05-16 14:28:18
【问题描述】:

在我的 Mapper 类中,我从 ZfcBase 扩展 AbstractDbMapper 以从数据库中获取行。一个简单的例子是这样的代码:

class MyMapper extends AbstractDbMapper
{

    //...

    public function fetchAll() {
        $select = $this->getSelect();
        return $this->select($select); // returns HydratingResultSet
    }
}

问题是$this->select() 返回一个Zend\Db\ResultSet\HydratingResultSet(包含需要的和水合的对象)。但我想返回这些对象的数组,而不是包含这些对象的 HydratingResultSet

首先要看的是HydratingResultSet::toArray(),但这会返回一个多维数组而不是对象数组。

所以我选择了手工制作:

public function fetchAll() {
        $select = $this->getSelect();

        $results = array();
        foreach ($this->select($select) as $object) {
            $results[] = $object;
        }
        return $results; // returns array of needed objects
}

这可行,但在每个 fetch 方法中看起来都很难看。我是否必须修改 select() 中的代码才能获得想要的行为,还是有更简单的方法?

顺便说一句:是否甚至建议返回一个数组或像这样转换它?感谢您的帮助!

【问题讨论】:

  • 你需要一个数组有什么原因吗?结果集可以很好地用作迭代器,并且可以在大多数情况下使用。没有内置方法可以在不执行您现在正在执行的操作的情况下获取数组,您可以将该方法添加到 Mapper 或只是 Hydrator 作为快捷方式.
  • 我在我的控制器中使用这些结果,并且认为使用数组而不是一些 Zend\Db 对象会更干净。我不明白他们为什么选择这样做......
  • 他们选择这样做是因为您可以获得额外的功能,例如缓冲结果集等。想想如果您有 900 万个对象的集合,您的数组将变得巨大并消耗 RAM,其中这个集合的项目是一次按需制作的,效率更高。
  • 好吧,这听起来很合理。非常感谢,我没有想到。如果有一个内置函数来检索整个数组,那至少会很好,因为这将满足大多数情况下恕我直言的需要。我现在手动添加。
  • 这确实是 Zend 内部的不一致。看到这个问题:github.com/zendframework/zf2/issues/4635

标签: zend-framework zend-framework2 zend-db


【解决方案1】:

更新:

这样做的可能性更小(来自https://stackoverflow.com/a/19266650/1275778 的豪华轿车)。从上面适应我的例子,它的工作原理是这样的:

public function fetchAll() {
    $select = $this->getSelect();
    $results = $this->select($select);
    return \Zend\Stdlib\ArrayUtils::iteratorToArray($results); // returns desired array of objects
}

如果 limos 在这里发布他的答案,我会很乐意接受。

旧答案:

由于没有人能回答我的问题,我尝试实现(对我而言)最简洁的选项:扩展 AbstractDbMapper 以添加上述功能。我在这里为任何寻求解决方案的人记录下来:

MyAbstractDbMapper extends AbstractDbMapper
{
    /**
     * @param Select $select
     * @param object|null $entityPrototype
     * @param HydratorInterface|null $hydrator
     * @return array
     */
    protected function select(Select $select, $entityPrototype = null, 
        HydratorInterface $hydrator = null)
    {
        $resultSet = parent::select($select, $entityPrototype, $hydrator);
        $results = array(); // Array of result objects
        foreach ($resultSet as $object) {
            $results[] = $object;
        }
        return $results;
    }
}

MyAbstractDbMapper 中的select() 现在返回一个对象数组,而不是 HydratingResultSet

由于这被否决了,有人可以解释一下原因吗?

【讨论】:

【解决方案2】:

通常你已经得到了对象类,所以只需弹出你的对象(类)的实例:

public function fetchById($id) {

    [...]

    $resultSet = $this->getDbTable()->fetchAll($select);
    $entries   = array();

    foreach ($resultSet as $row) {
        $entries[] = $this->populate($row);
    }

    return $entries;
}

并且填充函数可能看起来像这样:

private function populate($row)
{
    $entry = new Application_Model_YourModel();

    $entry->setId($row->id);

    [...] //set other object values

    return $entry;
}

这将返回一个对象数组

【讨论】:

  • 我的循环中的对象已经是所需的类型,因为HydratedResultSet 提供了一个迭代器来循环水合对象。所以这些不是行对象,并且已经在AbstractDbMapper 中进行了补充。因此不需要填充函数,也不需要使用 fetchAll,因为$this->select() 正在获取结果。
  • 好的。你用的是哪个版本的zend? toArray() 是否满足您的需求? tgaconnect.com/dox/zend/html/…
  • 我使用的是 ZF 2.2。不,toArray() 返回一个多维数组,因此根本不包含任何对象。
猜你喜欢
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 2018-12-04
  • 2021-06-16
相关资源
最近更新 更多