Доктрина ORM сериализации после объединения - PullRequest
3 голосов
/ 20 июня 2019

Ребята, я работаю с доктриной JOINS и столкнулся с проблемой.

Я выполнил запрос с объединениями, и, похоже, результаты хорошие!но вывод ужасен

public function getMarketcapData($page = -1, $limit = -1){
      $pageAndCount = $page>-1 && $limit>0;
      $qb = $this->getEntityManager()->createQueryBuilder();

      $q  = $qb->select('cc, count(cr) as coinRawsCount, cmc as relatedCategory')
              ->from('AppBundle:CoinClean', 'cc')
              ->leftJoin("AppBundle:CoinRaw", "cr",  'WITH', 'cc = cr.coinClean')
              ->leftJoin("AppBundle:CoinMapCategory", "cmc", 'WITH', 'cc.relatedCategory = cmc')
              ->andWhere('cc = cr.coinClean')
              ->andWhere('cc.relatedCategory = cmc')
              ->groupBy('cc.id')
      ;

      if($pageAndCount) $q = $q->setFirstResult($page*$limit)->setMaxResults($limit);

      $q= $q->orderBy('cc.rank', "ASC")->getQuery();

      $result = $q->getResult();
      if($pageAndCount){
          $qb = $this->getEntityManager()->createQueryBuilder();
          $q = $qb->select('count(u.id)')->from('AppBundle:CoinClean', 'u')->getQuery();
          return new PageResult($result, (int)$q->getSingleScalarResult(), $page, $limit );
      }else{
          return $result;
      }
  }

здесь у вас есть вывод: это массив из массива + obejcts

data:[
   [ // first query result
    {data from cc} // ony one object
   ], 
   {// first query result from join
     "coinRawsCount": 4,
     "relatedCategory": {...}
   },
   [ // second query result
     {data from cc2} // ony one object
   ], 
   {// second query result from join
    "coinRawsCount": 4,
    "relatedCategory": {...}
   }
]

моя цель - сжать все в

"data":[
  {
    "data": {...},
    "coinRawsCount": 4,
    "relatedCategory": {...}
  },
  {
    "data": {...},
    "coinRawsCount": 4,
    "relatedCategory": {...}
  },
]

Есть идеи?

1 Ответ

0 голосов
/ 20 июня 2019

Вы можете перебрать результат и объединить все остальные строки, например, как это:

$rows = $q->getResult();
$result = []

foreach ($rows as $index => $row) {
    if ($row instanceof App\Entity\CoinClean) {
        // Skip first row and merge data when reading next row
        continue;
    }
    $result[] = array_merge(
        ['data' => $rows[$index - 1]],
        $row
    );
}

return $result;

Предполагая, что первая строка всегда является сущностью, мы пропустим эту запись, используя continue;. Следующая строка должна содержать массив с дополнительными данными. Затем мы можем взять предыдущее смещение ($index - 1), чтобы получить запись и текущую строку и объединить их вместе. Возможно, вам придется сделать дополнительные проверки.

Имейте в виду, что вы будете перебирать потенциально большой массив, и, поскольку вы копируете данные в новый массив, это может занять значительное количество памяти. Поэтому вам, возможно, придется профилировать и оптимизировать его, если вы заметите низкую производительность.

Другими вариантами будет выполнение собственного запроса SQL, а затем просто отобразить выходные данные с помощью ResultSetMappingBuilder или использовать настраиваемую гидратацию, то есть создать новый настраиваемый DTO-объект для этого запроса, который лучше соответствует результирующие данные, чем исходная структура сущности, используя DQL SELECT NEW App\Dto\MyModel FROM ...your query...'.

...