Php 规则实体对象到数组

Php 规则实体对象到数组,php,arrays,doctrine-orm,doctrine,Php,Arrays,Doctrine Orm,Doctrine,要将实体对象转换为普通数组,这是我目前的代码 $demo = $this->doctrine->em->find('Entity\User',2); 获取实体对象 Entity\User Object ( [id:Entity\User:private] => 2 [username:Entity\User:private] => TestUser [password:Entity\User:private] => 950715f3f83e20ee1549

要将实体对象转换为普通数组,这是我目前的代码

 $demo = $this->doctrine->em->find('Entity\User',2);
获取实体对象

Entity\User Object
(
[id:Entity\User:private] => 2
[username:Entity\User:private] => TestUser
[password:Entity\User:private] => 950715f3f83e20ee154995cd5a89ac75
[email:Entity\User:private] => test@test.com
[firm_id:Entity\User:private] => Entity\Firm Object
    (
        [id:Entity\Firm:private] => 16
        [company_name:Entity\Firm:private] => TestFirm
        [company_detail:Entity\Firm:private] => India
        [created_at:Entity\Firm:private] => DateTime Object
            (
                [date] => 2014-08-01 18:16:08
                [timezone_type] => 3
                [timezone] => Europe/Paris
            )

        [user:Entity\Firm:private] => 
    )

[created_at:Entity\User:private] => DateTime Object
    (
        [date] => 2014-08-01 15:12:36
        [timezone_type] => 3
        [timezone] => Europe/Paris
    )

[updated_at:Entity\User:private] => DateTime Object
    (
        [date] => 2014-08-01 15:12:36
        [timezone_type] => 3
        [timezone] => Europe/Paris
    )

[firm:protected] => 
) ,
已尝试,但根据我的要求,不希望用户进行查询。
谢谢。

你可以试试这样的东西

    $result = $this->em->createQueryBuilder();
    $app_code = $result->select('p')
            ->from('YourUserBundle:User', 'p')
            ->where('p.id= :id')
            ->setParameter('id', 2)
            ->getQuery()
            ->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
另一方面,

 $this->em->getRepository('YourUserBundle:User')
      ->findBy(array('id'=>1));
上面将返回一个数组,但包含多个对象。返回数组的最佳方法是使用条令查询

希望这有帮助。
干杯

我对Symfony还不熟悉,但有一些工作方式(但很奇怪):

json_decode($this->container->get('serializer')->serialize($entity, “json”)


几个月前,我在我的存储库中创建了一个递归函数,它并不完美(比如,如果您有一个createdBy和updatedBy字段,它将只检索一个用户的值,因为使用$aClassNamesDone可以非常简单地防止递归),但它可能会有帮助:

    public function entityToArray($entity, &$aClassNamesDone=array(), $latestClassName="") {

    $result = array();

    if(is_null($entity)) {
        return $result;
    }

    $className = get_class($entity);

    // init with calling entity
    if(empty($aClassNamesDone)) {
        $aClassNamesDone[] =$className;
    }

    $uow = $this->getEntityManager()->getUnitOfWork();

    $entityPersister = $uow->getEntityPersister($className);
    $classMetadata = $entityPersister->getClassMetadata();

    //DEPENDS ON DOCTRINE VERSION
    //if(strstr($className, 'DoctrineProxies\\__CG__\\')){
    if(strstr($className, 'Proxies\\__CG__\\')){
        $uow->initializeObject($entity);
    }

    foreach ($uow->getOriginalEntityData($entity) as $field => $value) {

        if (isset($classMetadata->associationMappings[$field])) {

            $assoc = $classMetadata->associationMappings[$field];

            if (isset($classMetadata->columnNames[$field])) {
                $columnName = $classMetadata->columnNames[$field];
                $result[$columnName] = $value;
            }

            // to avoid recursivity we can look for the owning side (gives similar results as Query::HYDRATE_ARRAY):
            // elseif($assoc['isOwningSide']) { ...
            // or we can track entities explored and avoid any duplicates (this will however ignore some fields pointing to the same entity class)
            // for example: only one of createdBy, updatedBy will be kept

            else if(!in_array($assoc['targetEntity'], $aClassNamesDone) || $assoc['targetEntity'] == $latestClassName) {

                try {

                    if ($assoc['targetEntity'] != 'Timestamp') {

                        $aClassNamesDone[] = $assoc['targetEntity'];

                        $targetClass = $this->getEntityManager()->getClassMetadata($assoc['targetEntity']);

                        if (($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::MANY_TO_MANY) || ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY)) {

                            $getterName = 'get' . ucfirst($assoc['fieldName']);
                            $entityChildren = $entity->$getterName();
                            foreach ($entityChildren as $oneChild) {
                                $result[$assoc['fieldName']][] = $this->getEntityManager()->getRepository($assoc['targetEntity'])->entityToArray($oneChild, $aClassNamesDone, $assoc['targetEntity']);
                            }

                        } else if (($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_ONE) || ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::MANY_TO_ONE)) {

                            $getterName = 'get' . ucfirst($assoc['fieldName']);
                            $entityChild = $entity->$getterName();
                            $result[$assoc['fieldName']] = $this->getEntityManager()->getRepository($assoc['targetEntity'])->entityToArray($entityChild, $aClassNamesDone, $assoc['targetEntity']);

                        }
                    }

                } catch (\Exception $e) {
                    //var_dump('No entityToArray for ' . $assoc['targetEntity']);
                    throw ($e);
                }
            }

        }
    }

    return $result;
}

注意:如果您想要实体的数组表示是为了将其转换为JSON以获得AJAX响应,我建议您检查以下问答: . 我特别喜欢使用内置的JsonSerializable接口,这与我的答案类似


因为条令并没有提供一种将实体转换为关联数组的方法,所以您必须自己进行转换。一种简单的方法是创建一个基类,该基类公开一个返回实体数组表示形式的函数。这可以通过让基类函数本身调用来实现。此函数获取传入对象的可访问属性,并将其作为关联数组返回。然后,只要在创建要转换为数组的实体时扩展该基类即可

下面是一个非常简单的例子:

abstract class ArrayExpressible {
    public function toArray() {
        return get_object_vars($this);
    }
}

/** @Entity */
class User extends ArrayExpressible {

    /** @Id @Column(type="integer") @GeneratedValue */
    protected $id = 1; // initialized to 1 for testing

    /** @Column(type="string") */
    protected $username = 'abc';

    /** @Column(type="string") */
    protected $password = '123';

}

$user = new User();
print_r($user->toArray());
// Outputs: Array ( [id] => 1 [username] => abc [password] => 123 )
注意:必须保护实体的属性,以便基类可以使用
get\u object\u vars()


如果由于某种原因无法从基类进行扩展(可能是因为您已经扩展了基类),那么至少可以创建一个接口,并确保您的实体实现该接口。然后必须在每个实体内实现
toArray
函数

例如:

interface ArrayExpressible {
    public function toArray();
}

/** @Entity */
class User extends SomeBaseClass implements ArrayExpressible {

    /** @Id @Column(type="integer") @GeneratedValue */
    protected $id = 1; // initialized to 1 for testing

    /** @Column(type="string") */
    protected $username = 'abc';

    /** @Column(type="string") */
    protected $password = '123';

    public function toArray() {
        return get_object_vars($this);
        // alternatively, you could do:
        // return ['username' => $this->username, 'password' => '****']
    }

}

$user = new User;
print_r($user->toArray());
// Outputs: Array ( [id] => 1 [username] => abc [password] => 123 )
你可以用这个

$demo=array($demo);

如果你只需要访问一个值,你也可以这样做

如果“personType”是一个对象,而您需要关系的值

$personTypeId = $form->get('personType')->getViewData();
我需要一个toArray()方法,它可以在水合作用后工作,但是get_object_vars()技巧不起作用,因为doctrine 2.x中的延迟加载/代理内容

这是我的dropin方法

use Doctrine\Common\Inflector\Inflector;
...
public function toArray() {
    $methods = get_class_methods($this);
    $array = [];
    foreach ($methods as $methodName) {
        // remove methods with arguments
        $method = new \ReflectionMethod(static::class, $methodName);
        if ($method->getNumberOfParameters() > 0) continue;
        $matches = null;
        if (preg_match('/^get(.+)$/', $methodName, $matches)) {
            // beautify array keys
            $key = Inflector::tableize($matches[1]);
            // filter unwanted data
            if (in_array($key, ['object1', 'object2'])) continue;
            $array[$key] = call_user_func([$this, $methodName]);
        }
    }
    return $array;
}

请随意改进它

如果您已经从数据库中获取了对象实体,您还可以使用
DoctrineModule\Stdlib\Hydrator\DoctrineObject

/**
 * Assume your entity for which you want to create an array is in $entityObject.
 * And it is an instance of YourEntity::class.
 */
$tmpObject = new DoctrineObject($this->entityManager, YourEntity::class);
$data = $tmpObject->extract($entityObject);
现在,
$data
将以数组形式包含对象


另外,我不确定问这个问题时这是否可行。

试试这个
var\u dump(get\u object\u vars(object))?它不工作!谢谢,顺便说一句:)iswinky的解决方案只有在您的成员被声明为
public
时才有效。因为它们是私有的,所以它无法访问它们。但是,您可以向实体添加一个返回
get\u object\u vars($this)的函数并从外部调用。谢谢,但我已经提到,不想使用条令查询的东西。哦。很抱歉。难道你们不允许使用实体库吗?事实上,是的,你们能给我一个例子吗?这意味着并没有方法将实体对象转换成数组?是的,这很奇怪。到目前为止,我还没有找到这样的。当我有这样的需求时,我使用条令查询生成器并将结果添加到数组中。干杯。小心点,因为如果序列化程序试图从它的实体关系获取数据,那么这样你可能会得到一个讨厌的递归。谢谢你@le0diaz,我正在使用排除来避免一些递归。我遇到了同样的问题,最后也使用了排除。我需要它来使用@MaxDepth(n)注释,但它不能开箱即用。我必须更新我的控制器(从FOSRestController继承)以使用类似的东西,也许它也能帮助任何人:$view=$this->view($facility)$查看->getSerializationContext()->enableMaxDepthChecks();返回$this->handleView($view);您可以使用以下语法:
$this->container->get('serializer')->serialize($entity,'array')
您可以获得一个JSONECODE/jsondecode密码。请您解释一下,这是如何解决问题的。如果我对代码理解正确,您只需将
$demo
放入一个数组中。但问题是,如何将实体转换为数组;但我不知道它在条令对象中是否有效。我通过在preg_匹配检查中添加属性_exists()检查改进了它:
如果(!property_exists($this,$definctor->camelize($matches[1]))继续