php Doctrine 实体对象到数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25158549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 17:41:54  来源:igfitidea点击:

Doctrine entity object to array

phparraysdoctrine-ormdoctrine

提问by Wit Wikky

Wants to convert doctrine entiry object to normal array, this is my code so far,

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

 $demo = $this->doctrine->em->find('Entity\User',2);

Getting entity object ,

获取实体对象,

Entity\User Object
(
[id:Entity\User:private] => 2
[username:Entity\User:private] => TestUser
[password:Entity\User:private] => 950715f3f83e20ee154995cd5a89ac75
[email:Entity\User:private] => [email protected]
[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] => 
) ,

Tried this,But as per my requiremnet do not want to user doctrine_query. Thanks.

试过这个,但根据我的要求,不想用户学说_查询。谢谢。

回答by Anjana Silva

You can try something like this,

你可以试试这样的

    $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);

Another way,

其它的办法,

 $this->em->getRepository('YourUserBundle:User')
      ->findBy(array('id'=>1));

Above will return an array but contains doctrine objects. Best way to return an array is using the doctrine query.

以上将返回一个数组,但包含学说对象。返回数组的最佳方法是使用学说查询。

Hope this helps. Cheers!

希望这可以帮助。干杯!

回答by Kodos Johnson

Note:If your reason for wanting an array representation of an entity is to convert it to JSON for an AJAX response, I recommend checking this Q&A: How to encode Doctrine entities to JSON in Symfony 2.0 AJAX application?. I particularly like the one about using the built-in JsonSerializable interface which is similar to my answer.

注意:如果您想要实体的数组表示的原因是为了将其转换为 JSON 以进行 AJAX 响应,我建议您查看此问答: 如何在 Symfony 2.0 AJAX 应用程序中将 Doctrine 实体编码为 JSON?. 我特别喜欢关于使用内置 JsonSerializable 接口的那个,这与我的回答相似。



Since Doctrine does not provide a way to convert entities to associative arrays, you would have to do it yourself. One easy way is to create a base class that exposes a function that returns an array representation of the entity. This could be accomplished by having the base class function call get_object_varson itself. This functions gets the accessibleproperties of the passed-in object and returns them as an associative array. Then you would simply have to extend this base class whenever you create an entity that you would want to convert to an array.

由于 Doctrine 没有提供将实体转换为关联数组的方法,因此您必须自己完成。一种简单的方法是创建一个基类,该基类公开一个返回实体数组表示的函数。这可以通过get_object_vars对自身进行基类函数调用来实现。此函数获取传入对象的可访问属性并将它们作为关联数组返回。然后,每当您创建要转换为数组的实体时,您只需扩展此基类。

Here is a very simple example:

这是一个非常简单的例子:

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 )

Note: You must make the entity's properties protected so the base class can access them using get_object_vars()

注意:您必须保护实体的属性,以便基类可以使用 get_object_vars()



If for some reason you cannot extend from a base class (perhaps because you already extend a base class), you could at least create an interfaceand make sure your entities implement the interface. Then you will have to implement the toArrayfunction inside each entity.

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

Example:

例子:

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 )

回答by antongorodezkiy

I'm new to Symfony, but there is some working (but strange) way:

我是 Symfony 的新手,但有一些有效(但很奇怪)的方法:

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

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

回答by Fazhom Arnaud

I made a recursive function in my Repository a few months ago, it's not perfect (like, if you have a field createdBy and updatedBy, it will only retrieve the value for one user because of a rather simple protection against recursivity with $aClassNamesDone), but it may help:

几个月前我在我的 Repository 中做了一个递归函数,它并不完美(比如,如果你有一个字段 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;
}

回答by Tom Olson

If you just need to access a single value, you can also do this...

如果您只需要访问单个值,您也可以这样做...

If 'personType' were an object and you wanted the value of the relationship...

如果“personType”是一个对象并且您想要关系的值...

$personTypeId = $form->get('personType')->getViewData();

回答by quazardous

I needed a toArray() method that could work after hydration but the get_object_vars() trick did not work because of the lazy loading/proxy stuff in doctrine 2.x

我需要一个可以在水化后工作的 toArray() 方法,但是 get_object_vars() 技巧没有工作,因为在 Dotst 2.x 中延迟加载/代理的东西

so here is my dropin method

所以这是我的 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;
}

feel free to improve it

随意改进它

回答by cb0

If you alread have the object entity fetched form the database, you could also work with the DoctrineModule\Stdlib\Hydrator\DoctrineObject.

如果您已经从数据库中获取了对象实体,您还可以使用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);

Now $datawill contain your object as array.

现在$data将包含您的对象作为数组。

P.S. I'm not sure this was possible when the question was asked.

PS我不确定当问到这个问题时这是可能的。

回答by kishan

Simply u can use this

简单地你可以使用这个

$demo=array($demo);