学说水合阵列结果

时间:2014-03-19 16:48:01

标签: php zend-framework doctrine-orm

我想让Doctrine返回一个水合数组,其值为键的id,然后是结果数组中的所有值(即如果有多个具有相同ID的项,则返回ID,其中包含多个结果的数组)。

这是我当前的功能:

    public static function getMedia($em, $entity, $id = NULL)
    {
        $dql = 'SELECT m.id, m.url, m.nb, m.lang
            FROM iMT\Entity\Media m INDEX BY m.id JOIN iMT\Entity\\' . $entity . ' r WITH m.id = r.id';

        if($id) {
            $dql .= " WHERE r.id = ?1";
        }

        $q = $em->createQuery($dql);

        if($id) {
            $q->setParameter(1, $id);
        }

        return $q->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
    }

返回:

array (size=44)
  479600 => 
    array (size=4)
      'id' => int 479600
      'url' => string 'pois/479600/Nonna.JPG' (length=48)
      'nb' => null
      'lang' => string 'fr' (length=2)
  479615 => 
    array (size=4)
      'id' => int 479615
      'url' => string 'pois/479615/Tramways.jpg' (length=51)
      'nb' => null
      'lang' => string 'fr' (length=2)
  479580 => 
    array (size=4)
      'id' => int 479580
      'url' => string 'pois/479580/ATLAS.jpg' (length=48)
      'nb' => null
      'lang' => string 'fr' (length=2)
  479581 => 
    array (size=4)
      'id' => int 479581
      'url' => string 'pois/479581/P'tit_sushi.jpg' (length=54)
      'nb' => null
      'lang' => string 'fr' (length=2)

但是,我需要输出:

array (size=44)
  479600 => 
    array (size=2)
        array (size=4)
          'id' => int 479600
          'url' => string 'pois/479600/Nonna.JPG' (length=48)
          'nb' => null
          'lang' => string 'fr' (length=2)
        array (size=4)
          'id' => int 479600
          'url' => string 'pois/479600/OtherPic.JPG' (length=48)
          'nb' => null
          'lang' => string 'fr' (length=2)

我是否需要创建自己的AbstractQuery :: HYDRATE_ARRAY,或者是否有可以满足我需要的东西?

我通过检查它是否包含与当前项的ID匹配的键来使用结果(例如if(isset($ data [$ item]))//其中$ item = 479600然后输出图像),也许有更好的方法来检查结果?

修改
我更新了我的函数返回:

    $result = $q->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);

    $data = array();
    $count = count($result);
    for($i = 0; $i < $count; $i++) {
        if(!isset($data[$result[$i]['id']])) {
            $data[$result[$i]['id']] = array(
                    $result[$i]
                );
        } else {
            $data[$result[$i]['id']][] = $result[$i];
        }
    }

    return $data;

更多地返回我想要的东西:

array (size=44)
  479600 => 
    array (size=1)
      0 => 
        array (size=4)
          'id' => int 479600
          'url' => string 'pois/479600/Nonna.JPG' (length=48)
          'nb' => null
          'lang' => string 'fr' (length=2)
  479577 => 
    array (size=2)
      0 => 
        array (size=4)
          'id' => int 479577
          'url' => string 'pois/479577/AOMC.JPG' (length=47)
          'nb' => null
          'lang' => string 'fr' (length=2)
      1 => 
        array (size=4)
          'id' => int 479577
          'url' => string 'pois/479577/Buffet AOMC.jpg' (length=54)
          'nb' => null
          'lang' => string 'fr' (length=2)

这可以改善吗?是否有任何可以帮助的Doctrine函数,或者我应该离开for()循环?

1 个答案:

答案 0 :(得分:2)

INDEX BYJOIN一起使用的问题在于,教条给出的结果可能不包含从数据库中提取的所有数据。

在您的情况下,数据库可能会返回包含m.id相同值的多行(因为JOIN)。但是,包含m.id相同值的每个后续行都将覆盖前一行(因为INDEX BY m.id)。

Doctrine 带有一个可以解决这个问题的保湿器。你确实需要实现自己的。详细了解如何创建custom hydration modes

<强>替代

另一种解决方案是在这种情况下使用INDEX BY

您可以编写一个存储库方法,将Doctrine给出的结果转换为您想要的数组。然后,应用程序的其他部分可以调用该存储库方法。

这可能比创建自定义水合模式更容易。

<强>更新

翻译可能如下所示:

$data = array();

foreach ($q->getArrayResult() as $row) {
    if (!isset($data[$row['id']])) {
        $data[$row['id']] = array();
    }

    $data[$row['id']][] = $row;
}

return $data;