2011-05-27 2 views
4

iv'e eu un problème pour recevoir un tableau complet (avec toutes les données des collections enfants intégrées et les objets) de mon document. Mon document ressemble exactement à celui-ci:Doctrine ODM (MongoDB) - Obtenir un tableau complet d'un objet?

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; 
    } 

} 


... 

je besoin d'une gamme complète d'une collection intégrée à la sortie l'ensemble des données et de le rendre par JSON. Ma requête ressemble à ceci:

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

Par exemple, si j'appelle la fonction toArray() comme ceci:

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

Ensuite, la sortie ist juste un tableau au niveau supérieur:

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

Comment puis-je obtenir facilement un tableau comme celui-ci?

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

Y a-t-il des meilleures pratiques ou peut-être quelques scripts d'aide manquants pour empêcher quelque chose de laid comme ce code (comment gérer enfant -> enfant -> enfant szenarios laid -> laid laid -> laid laid laid -> ...):

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

Merci beaucoup, Stephan

Répondre

11

réponse Bon sang est simple! Utilisez juste -> hydrate (faux) et c'est fait.

Pour repérer les requêtes les résultats par défaut sont hydratés et vous obtenez documents objets retour au lieu de tableaux. Vous pouvez désactiver cela et les résultats bruts directement retour de mongo en utilisant l'hydrate (false) Méthode :

<?php 

$users = $dm->createQueryBuilder('User') 
    ->hydrate(false) 
    ->getQuery() 
    ->execute(); 

print_r($users); 
+3

Oui, mais si vous avez [la logique de migration du schéma] (http://jwage.com/2010/07/30/doctrine-mongodb-odm-schema-migrations/) dans votre modèle? Tout cela serait sauté si vous contourniez l'hydrate. – anushr

+0

Si vous avez une logique de migration de schéma, vous pouvez implémenter une fonction toArray() pour vos documents où vous chargez toutes les méthodes get() du document et le renvoyez en tant que tableau – Gigala

1

je suis tombé sur ce même besoin récemment et a résolu le problème en créant une classe de base pour toutes mes entités avec une fonction toArray() et JsonSerializable. Il convertit également toutes les références imbriquées.

/** 
* @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; 
    } 
} 

Maintenant, je peux sérialiser l'entité en tant que tableau ou chaîne json avec json_encode ($ doc). Bam.

0

Réservoirs à Rooster242, vous pouvez même appliquer récursive toArray aux documents incorporés qui themself en utilisant BaseDocument étend le php is_subclass_of fonction:

/** 
* @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

Juste fait cela un peu plus générique, fonctionne parfaitement. N'oubliez pas de l'étendre avec vos documents et vos documents.

<?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; 
    } 
} 
Questions connexes