Doctrine ODM(MongoDB) - 获取一个完整的对象数组?

时间:2011-05-27 16:32:29

标签: mongodb doctrine doctrine-orm

我遇到了一个问题,即收到我文档的完整数组(带有嵌入式子集合和对象的所有数据)。我的文档看起来与此完全相同:

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

}


...

我需要一个完整的嵌入式集合数组来输出整个数据并通过json 进行渲染。我的查询如下:

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

例如,如果我像这样调用toArray()函数:

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

然后输出只是顶层的数组:

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

我怎样才能轻松获得这样的数组呢?

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

是否有任何最佳做法或可能缺少帮助脚本来防止像这段代码一样难看的东西(如何处理孩子 - >孩子 - >孩子szenarios?丑陋 - >丑陋丑陋 - >丑丑丑陋 - &gt ; ...):

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

非常感谢, 斯蒂芬

4 个答案:

答案 0 :(得分:12)

该死的简单回答!只需使用 - >水合物(假)就完成了。

  

用于查找查询结果   默认是含水的,你得到   记录对象而不是   阵列。你可以禁用它并获取   原始结果直接来自   mongo使用水合物(假)   方法:

<?php

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

print_r($users);

答案 1 :(得分:1)

我最近遇到了同样的需求并通过使用toArray()函数和JsonSerializable为我的所有实体创建基类来解决它。它也会转换所有嵌套引用。

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

现在我可以使用json_encode($ doc)将实体序列化为数组或json字符串。的Bam

答案 2 :(得分:0)

坦克到Rooster242,您甚至可以通过使用php is_subclass_of 函数递归地应用toArray来嵌入自己扩展BaseDocument的文档:

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

答案 3 :(得分:0)

让这更加通用,做得很完美。只是不要忘记用你的文档和嵌入扩展它。

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