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

Doctrine ODM(MongoDB)-获取对象的完整数组?,mongodb,doctrine,doctrine-orm,Mongodb,Doctrine,Doctrine Orm,iv'e在接收我的文档的完整数组(包含嵌入的childs集合和对象的所有数据)时遇到问题。我的文档与此文档完全相同: use Doctrine\Common\Collections\ArrayCollection; /** @Document(collection="user") */ class User { /** @Id */ protected $id; /** @String */ protected $firstname; /** @String */ protected $

iv'e在接收我的文档的完整数组(包含嵌入的childs集合和对象的所有数据)时遇到问题。我的文档与此文档完全相同:

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();
$array = $result->getSubscription()->toArray();
print_r($array);

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

$query = $this->_dbContainer->getDocumentManager()->createQueryBuilder('User')->field('deletedAt')->exists(false);                          
$result = $query->field('id')->equals($id)->getQuery()->getSingleResult();
$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', ...)
...

是否有任何最佳实践或某些缺少的帮助程序脚本来防止类似此代码的丑陋行为(如何处理child->child->child szenarios?丑陋->丑陋->丑陋->):

非常感谢,
斯蒂芬

他妈的回答很简单!只要使用->水合物(false)就可以了

对于查找查询,结果按 如果你补充了水分,你就会 返回文档对象,而不是 数组。您可以禁用此功能并获取 原始结果直接从 使用水合物的mongo(错误) 方法:


我最近遇到了同样的需求,并通过使用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.

对于Rooster242,您甚至可以递归地将数组应用于嵌入文档,通过使用php是函数的子类来扩展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;
    }
}

只是让它更通用一点,很完美。只是别忘了用文档和嵌入来扩展它

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

是的,但是如果您的模型中有呢?如果您绕过Hyde,所有这些都将被跳过。如果您有架构迁移逻辑,您可以为您的文档实现toArray()-函数,在其中加载文档的所有get()方法并将其作为数组返回