4

Doing this in a symfony2 controller results in an array where each single result is itself an object.. but i need it to be an array as well so i can easily json_encode the whole list

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

So how do i get an array of arrays and not an array of objects which is what i'm getting by using HYDRATE_ARRAY?

2 Answers 2

4

I ended up installing the JMSSerializerBundle which provides the methods I needed. Since I had a linked entity and I did not need the linked object, in my entity class i now have

...
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

By adding the @ExclusionPolicy("None") all properties should be serialized except those marked with exclude. Then, in the linked entitites in the same class just add the exclude annotation

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

and so in the controller i can now do (after adding use Symfony\Component\HttpFoundation\Response;)

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

And that's that. Symfony+Doctrine can make some simple things complicated.

Sign up to request clarification or add additional context in comments.

Comments

2

There's no way, out-of-the-box, to tell Doctrine to treat an object as an array. However, with a little tweaking and some questionable design decisions, you can achieve this.

The first thing you need to do, is create a base class (for your classes to extend) that implements the ArrayAccess interface. An article describing this can be found in the Doctrine cookbook. It will look something like this:

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!"
        );
    }

}

Then, when you create your model classes (or at least the ones that you want to treat as arrays), you'll need to extend this DomainObject class. The last piece of the puzzle is to make your class properties public in order to give the json_encode function the ability to inspect your class properties and use them as keys for the json object.

NB: using public properties in classes can lead to a lot of hard to trace bugs and is generally considered questionable practice. this is just an example that i whipped up quickly to illustrate how it could be accomplished. I'm sure there is a more elegant way to implement this that doesn't require public properties. This solution is just meant to get the ball rolling

An example domain class might look something like this:

class Tester extends DomainObject
{

    public $foo;

    public $bar;

    public function __construct($foo, $bar)
    {

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

    }

}

Now you'll be able to cast an instance of the Tester class to an array and pass that array to json_encode:

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

Which will produce the following output:

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

EDIT: just to bring your code snippet back into context. You don't need to use HYDRATE_ARRAY anymore, it would just look like this:

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

provided your Report class extends the DomainObject class defined above.

1 Comment

thanks for the help but as you pointed out it isn't the best solution to expose the entity's properties so i went with the solution i posted below.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.