Question

Here are two sample classes I have:

/** @ODM\Document */
class Product implements JsonSerializable{

  /** @ODM\String */
  protected $some_property;

  /** @ODM\EmbedMany */
  protected $attributes;

  public function jsonSerialize(){
    $o = new StdClass();
    $o->property = $this->some_property;
    $o->attributes = $this->attributes;
    return $o;
  }
}

/** @ODM\EmbeddedDocument */
class Attribute implements JsonSerializable{

  /** @ODM\String */
  protected $some_property;

  public function jsonSerialize(){
    $o = new StdClass();
    $o->property = $this->some_property;
    return $o;
  }
}

In my code, I create an instance of Product, and then some processes create an array of Attribute instances on $product->attributes. I persist the Product instance without a problem into mongoDB using Doctrine ODM. I can go into the DB (using rockmongo), and I see the presisted document, and the annotations on the JSON view to the class of the attributes array:

"_doctrine_class_name": "\Attribute"

But when I query for that product using the QueryBuilder, instead of getting an array of Attribute instances, I get a PersistentCollection (looking at the isntance with the debugger at runtime).

I believe this has to do with lazy loading, but its breaking up my code. When I try to call json_encode($product), instead of cascading through to each of the Attribtue instances, it just returns an empty array.

Here is what I expect to get form a json_encode():

{
    "property": "some product value",
    "attributes": [
        {
            "property": "some attribute value"
        },
        {
            "property": "some attribute value"
        }
    ]
}

Is there any way to either disable lazy loading, or force the proper instantiation of each Attribute instance? Or any other way to be able to get the desired JSON object, without having to manually traversing the whole structure? Thanks!

Was it helpful?

Solution

How I ended up solving the issue of lazy-loading:

// parent jsonSerialize method
public function jsonSerialize(){
  $o = new StdClass();
  $o->property = $this->some_property;
  $a = [];
  foreach($this->attributes as $attr){
    $a[] = $attr;
  }
  $o->attributes = $a;
  return $o;
}

This forces the PersistentCollection object to spit our one by one the proper instances, and then the jsonSerializable methods respond well cascaded through.

Ugly IMO, but solves the issue. Sadly, you have to apply this on every Embedded Object dependency you have.

Hole it helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top