Doctrine ODM (MongoDB) - Get the full array of an object?

iv'e there was a problem with getting the full array (with all the data of the built-in child collections and objects) of my document. My document looks exactly like this:

use Doctrine\Common\Collections\ArrayCollection; /** @Document(collection="user") */ class User { /** @Id */ protected $id; /** @String */ protected $firstname; /** @String */ protected $lastname; /** @EmbedMany(targetDocument="Email") */ protected $email; /** @EmbedMany(targetDocument="Address") */ protected $address; /** @EmbedMany(targetDocument="Subscription") */ protected $subscription; /** * Construct the user * * @param array $properties * @throws User_Exception */ public function __construct(array $properties = array()) { $this->email = new ArrayCollection(); $this->address = new ArrayCollection(); $this->subscription = new ArrayCollection(); foreach($properties as $name => $value){ $this->{$name} = $value; } } ... 

I need a full array of inline collection to output all the data and render json . My query looks like this:

 $query = $this->_dbContainer->getDocumentManager()->createQueryBuilder('User')->field('deletedAt')->exists(false); $result = $query->field('id')->equals($id)->getQuery()->getSingleResult(); 

For example, if I call the toArray() function as follows:

 $array = $result->getSubscription()->toArray(); print_r($array); 

Then the output ist just an array at the top level:

 [0] => Object Subscription... [1] => Object Subscription... ... 

How can I easily get such an array?

 [0] => array('subscriptionLabel' => 'value1', 'field' => 'value1', ...) [1] => array('subscriptionLabel' => 'value2', 'field' => 'value2', ...) ... 

Are there any recommendations or maybe some missing helper scripts to prevent something ugly like this code (how to handle child → child → child szenarios? Ugly → ugly ugly → ugly ugly ugly ugly → ...)

 $example = array(); foreach($result->getSubscription() as $key => $subscription) { $example[$key]['subscriptionLabel'] = $subscription->getSubscriptionLabel(); $example[$key]['field'] = $subscription->getField(); ... } 

Thanks a lot Stephan

+4
source share
4 answers

Damn it, just the answer! Just use -> hydrate (false) and it is done.

To find queries, perform hydration by default, and you get return document objects instead of arrays. You can disable this and get the initial results directly mongo using the hydrate (false) Method:

 <?php $users = $dm->createQueryBuilder('User') ->hydrate(false) ->getQuery() ->execute(); print_r($users); 
+11
source

Recently, I ran into the same problem and solved it by creating a base class for all my objects with the toArray () function and JsonSerializable. It also converts all nested links.

 /** * @ODM\MappedSuperclass */ abstract class BaseDocument implements \JsonSerializable { public function jsonSerialize() { return $this->toArray(); } public function toArray() { $getter_names = get_class_methods(get_class($this)); $gettable_attributes = array(); foreach ($getter_names as $key => $funcName) { if(substr($funcName, 0, 3) === 'get') { $propName = strtolower(substr($funcName, 3, 1)); $propName .= substr($funcName, 4); $value = $this->$funcName(); if (is_object($value) && get_class($value) == 'Doctrine\ODM\MongoDB\PersistentCollection') { $values = array(); $collection = $value; foreach ($collection as $obj) { $values[] = $obj->toArray(); } $gettable_attributes[$propName] = $values; } else { $gettable_attributes[$propName] = $value; } } } return $gettable_attributes; } } 

Now I can serialize the object as an array or json string with json_encode ($ doc). Bam.

+1
source

Tanks for Rooster242, you can even recursively apply toArray to embedded documents that extend BaseDocument themselves using the php is_subclass_of function:

 /** * @ODM\MappedSuperclass */ abstract class BaseDocument implements \JsonSerializable { public function jsonSerialize() { return $this->toArray(); } public function toArray() { $getter_names = get_class_methods(get_class($this)); $gettable_attributes = array(); foreach ($getter_names as $key => $funcName) { if(substr($funcName, 0, 3) === 'get') { $propName = strtolower(substr($funcName, 3, 1)); $propName .= substr($funcName, 4); $value = $this->$funcName(); if (is_object($value) && is_subclass_of($value,"BaseDocument")) { $gettable_attributes[$propName] = $value->toArray(); } elseif (is_object($value) && get_class($value) == 'Doctrine\ODM\MongoDB\PersistentCollection') { $values = array(); $collection = $value; foreach ($collection as $obj) { if (is_subclass_of($obj,"BaseDocument")) { $values[] = $obj->toArray(); } else { $values[] = $obj; } } $gettable_attributes[$propName] = $values; } else { $gettable_attributes[$propName] = $value; } } } return $gettable_attributes; } } 
0
source

Just made it a little more general, works great. Just remember to renew it with your documents and paste.

 <?php namespace App\Documents; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Doctrine\ODM\MongoDB\PersistentCollection; /** * @ODM\MappedSuperclass */ abstract class BaseDocument implements \JsonSerializable { /** * @return array */ public function jsonSerialize() { return $this->toArray(); } /** * @return array */ public function toArray() { $getterNames = get_class_methods(get_class($this)); $gettableAttributes = []; foreach ($getterNames as $funcName) { if (substr($funcName, 0, 3) !== 'get') { continue; } $propName = strtolower(substr($funcName, 3, 1)); $propName .= substr($funcName, 4); $value = $this->$funcName(); $gettableAttributes[$propName] = $value; if (is_object($value)) { if ($value instanceof PersistentCollection) { $values = []; $collection = $value; foreach ($collection as $obj) { /** @var BaseDocument $obj */ if ($obj instanceof \JsonSerializable) { $values[] = $obj->toArray(); } else { $values[] = $obj; } } $gettableAttributes[$propName] = $values; } elseif ($value instanceof \JsonSerializable) { /** @var BaseDocument $value */ $gettableAttributes[$propName] = $value->toArray(); } } } return $gettableAttributes; } } 
0
source

All Articles