M.Z.
M.Z.

Reputation: 401

Symfony 3.2 ODM Doctrine array of MongoId's

How to make array of MongoId's in Symfony 3.2 Doctrine ODM serialized/deserialized properly ?

Document

namespace Acme\StoreBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * @MongoDB\Document(collection="Voter")
 */

class Voter
{

/**
 * @MongoDB\Id
 */
protected $id;


/**
 * @MongoDB\Collection
 */

protected $inlist;


/**
 * Get id
 *
 * @return id $id
 */
public function getId()
{
    return $this->id;
}

public function setId($id)
{
    $this->id = $id;
    return $this;
}


/**
 * Set inlist
 *
 * @param collection $inlist
 * @return $this
 */
public function setInlist($inlist)
{
    $this->inlist = $inlist;
    return $this;
}

/**
 * Get inlist
 *
 * @return collection $inlist
 */
public function getInlist()
{
    return $this->inlist;
}

}

Controller:

/**
 * @Route("/voter/{id}")
 * @Method({"GET"})
 */

public function getAction($id)
{
    $product = $this->get('doctrine_mongodb')
        ->getRepository('AcmeStoreBundle:Voter')
        ->find($id);

    if (!$product) {
        throw $this->createNotFoundException('No product found for id ' . $id);
    }

    $serializer = $this->get('serializer');

    $data = $serializer->serialize(
        $product,
        'json'
    );

    $response = new JsonResponse();
    $response->setContent($data);
    return $response;
}

Serialized Json:

{
"id": "593e99a8de6c84f5ecec3094",
"inlist": [
    {
        "timestamp": 1417718686,
        "pID": 3335,
        "inc": 9127278,
        "$id": "5480ab9e282e26070d8b456e"
    },
    {
        "timestamp": 1417718686,
        "pID": 3335,
        "inc": 9127273,
        "$id": "5480ab9e282e26070d8b4569"
    },
    {
        "timestamp": 1417718686,
        "pID": 3335,
        "inc": 9127272,
        "$id": "5480ab9e282e26070d8b4568"
    },
    {
        "timestamp": 1417718686,
        "pID": 3335,
        "inc": 9127275,
        "$id": "5480ab9e282e26070d8b456b"
    },
    {
        "timestamp": 1417718686,
        "pID": 3335,
        "inc": 9127274,
        "$id": "5480ab9e282e26070d8b456a"
    },
    {
        "timestamp": 1411754988,
        "pID": 2674,
        "inc": 9127271,
        "$id": "5425abec8f3723720a8b4567"
    }
]
}

I want it to be serialized to be an array of (string) id's, and deserialize it back to array of MongoId's:

{
"id": "593e99a8de6c84f5ecec3094", 
"inlist": ['5425abec8f3723720a8b4567', '5480ab9e282e26070d8b456b' ...]
}

Upvotes: 0

Views: 179

Answers (2)

M.Z.
M.Z.

Reputation: 401

setter/getter way worked for me even with serializer / deserializer

/**
 * Set actions
 *
 * @param collection $actions
 * @return $this
 */
public function setActions($actions)
{
    $re = [];
    foreach ($actions as $action) {
        $action['cid'] = new \MongoId($action['cid']);
        $re[] = $action;
    }

    $this->actions = $re;
    return $this;
}

/**
 * Get actions
 *
 * @return collection $actions
 */
public function getActions()
{
    $re = [];
    foreach ($this->actions as $action) {
        $action['cid'] = (string)$action['cid'];
        $re[] = $action;
    }

    return $re;
}

Upvotes: 0

malarzm
malarzm

Reputation: 2966

Since you mentioned "right way" in the comments here's how I would do it:

class VoterAPIRepresentation
{
    public $id;

    public $inlist = [];

    public function __construct(Voter $voter)
    {
        $this->id = (string) $voter->id;
        foreach ($voter->inlist as $i) {
            $this->inlist[] = (string) $i['$id'];
        }
    }
}

Above class is responsible for data representation in API since entity itself shouldn't be concerned with that. Then in controller:

public function getAction($id)
{
    $product = $this->get('doctrine_mongodb')
        ->getRepository('AcmeStoreBundle:Voter')
        ->find($id);

    if (!$product) {
        throw $this->createNotFoundException('No product found for id ' . $id);
    }

    $serializer = $this->get('serializer');

    $data = $serializer->serialize(
        new VoterAPIRepresentation($product),
        'json'
    );

    $response = new JsonResponse();
    $response->setContent($data);
    return $response;
}

Pro of this approach is that if you change the entity you don't need to be concerned with any endpoints and data they're returning since these two beings are not connected. On the other hand writing such classes is quite boring BUT it pays off for complex objects and representations.

Upvotes: 1

Related Questions