Symfony2 и Doctrine - возвращают результат базы данных в виде массива массивов в контроллере - PullRequest
4 голосов
/ 13 декабря 2011

Выполнение этого в контроллере symfony2 приводит к массиву, где каждый отдельный результат сам по себе является объектом ... но мне нужно, чтобы он также был массивом, чтобы я мог легко json_encode весь список

$em->getRepository('MyBundle:Report')->findByEvaluation($evaluation_id, \Doctrine\ORM\Query::HYDRATE_ARRAY)

Итак, как мне получить массив массивов, а не массив объектов, который я получаю, используя HYDRATE_ARRAY?

Ответы [ 2 ]

4 голосов
/ 13 декабря 2011

В итоге я установил JMSSerializerBundle , который предоставляет необходимые мне методы.Поскольку у меня была связанная сущность, и мне не был нужен связанный объект, в моем классе сущности теперь у меня есть

...
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Exclude;
/**
 * Iddp\RorBundle\Entity\Report
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Iddp\RorBundle\Entity\ReportRepository")
 * @ExclusionPolicy("None")
 */
class Report

. При добавлении @ExclusionPolicy ("None") все свойства должны быть сериализованы, кроме тех, которые отмеченыисключить.Затем в связанных правах в том же классе просто добавьте аннотацию исключения

/**
 * @ORM\ManyToOne(targetEntity="Client", inversedBy="reports")
 * @ORM\JoinColumn(name="client_id", referencedColumnName="id")
 * @Exclude
 */
protected $client;

, и теперь в контроллере я могу это сделать (после добавления используйте Symfony \ Component \ HttpFoundation \ Response;)

$serializer = $this->container->get('serializer');
$reports = $serializer->serialize($reports, 'json');
return new Response($reports);

И это все.Symfony + Doctrine может усложнить некоторые простые вещи.

2 голосов
/ 13 декабря 2011

Нет способа, из коробки, сказать Doctrine, чтобы он рассматривал объект как массив.Тем не менее, с небольшими изменениями и некоторыми сомнительными проектными решениями, вы можете достичь этого.

Первое, что вам нужно сделать, - это создать базовый класс (для расширения ваших классов), который реализует интерфейс ArrayAccess.Статью, описывающую это, можно найти в Поваренной книге Доктрины .Это будет выглядеть примерно так:

abstract class DomainObject implements ArrayAccess
{

    public function offsetExists($offset)
    {
        return isset($this->$offset);
    }

    public function offsetSet($offset, $value)
    {
        throw new BadMethodCallException(
            "Array access of class " . get_class($this) . " is read-only!"
        );
    }

    public function offsetGet($offset)
    {
        return $this->$offset;
    }

    public function offsetUnset($offset)
    {
        throw new BadMethodCallException(
            "Array access of class " . get_class($this) . " is read-only!"
        );
    }

}

Затем, когда вы создаете свои классы моделей (или, по крайней мере, те, которые вы хотите рассматривать как массивы), вам необходимо расширить этот класс DomainObject.Последний кусок головоломки - сделать свойства вашего класса общедоступными , чтобы дать функции json_encode возможность проверять свойства вашего класса и использовать их в качестве ключей для объекта json.

NB : использование открытых свойств в классах может привести к множеству трудных для отслеживания ошибок и обычно считается сомнительной практикой.это всего лишь пример, который я быстро набросал, чтобы проиллюстрировать, как это можно сделать.Я уверен, что есть более элегантный способ реализовать это, не требующий открытых свойств.Это решение предназначено только для того, чтобы заставить мяч катиться

Пример класса домена может выглядеть примерно так:

class Tester extends DomainObject
{

    public $foo;

    public $bar;

    public function __construct($foo, $bar)
    {

        $this->foo = $foo;
        $this->bar = $bar;

    }

}

Теперь вы сможете приводить экземпляр класса Tester кмассив и передать этот массив в json_encode:

$test = new Tester('Hello', 'World');
echo json_encode((array)$test);

, который выдаст следующий вывод:

{"foo":"Hello","bar":"World"}

EDIT : просто чтобы вернуть фрагмент кода вконтекст.Вам больше не нужно использовать HYDRATE_ARRAY, это будет выглядеть так:

$results = $em->getRepository('MyBundle:Report')->findByEvaluation($evaluation_id);
foreach ($results as $result) {
    echo json_encode((array)$result);
}

, если ваш класс Report расширяет класс DomainObject, определенный выше.

...