原则实体对象到数组


Doctrine entity object to array

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

 $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] => 
) ,

试过了,但是根据我的要求,我不想使用doctrine_query。谢谢。

你可以尝试这样做,

    $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));
上面的

将返回一个数组,但包含教条对象。返回数组的最佳方法是使用原则查询。

希望这对你有帮助。干杯!

注意:如果你想要一个实体的数组表示的原因是将其转换为JSON AJAX响应,我建议检查这个问题& &;A:如何在Symfony 2.0 AJAX应用程序中编码Doctrine实体到JSON ?我特别喜欢使用内置的JsonSerializable接口,这与我的答案相似。


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

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

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_object_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 )

如果您已经从数据库中获取了对象实体,您也可以使用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将包含您的对象作为数组。

注:

我是Symfony的新手,但有一些工作(但奇怪)的方式:

json_decode ($ this ->容器->获得(序列化)->序列化(美元)的实体,json))

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

这是我的drop方法

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

请随意修改

几个月前我在我的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;
}

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

如果'personType'是一个对象,而你想要的是关系的值…

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

如果有人想使用原则2,用UnitOfWork API来做。这是使用doctrine公共API的唯一方法。

: -

$em = $this->getEntityManager();
$uow = $em->getUnitOfWork();
$entity = $this->find($id);
// Returning the fetched data as an array
$uow->getOriginalEntityData($entity); // ['name' => 'Old Name', 'username'=> 'oldone']
// But it will not be synchronized with the entity
$entity->setName('New Name');
$uow->getOriginalEntityData($entity); // ['name' => 'Old Name', 'username'=> 'oldone']
// Luckily, there is a way to get changed data after called persist
$em->persist($entity);
$uow->getOriginalEntityData($entity); // ['name' => 'Old Name', 'username'=> 'oldone']
$uow->getEntityChangeSet($entity); // ['name' => ['Old Name', 'New Name']]
// Original data was syncronized after called flush method
$em->flush();
$uow->getOriginalEntityData($entity); // ['name' => 'New Name', 'username'=> 'oldone']

阅读我的博客文章了解更多信息。https://whizsid.github.io/blog/25/converting-a-doctrine-2-entity-to-an-array.html

这是我的工作

       $sql="
            SELECT * FROM users
        ";
        $stmt = $this->em->getConnection()->prepare($sql);
        $users =  $stmt->executeQuery()->fetchAllAssociative();

现在有点老了,但是你也可以创建一个简单的DataModel,你的实体可以从它扩展,然后创建一个__toArray()方法。

你不能使用get_object_vars(),因为它只拾取公共作用域的属性,并且它们都应该是私有的,但是你的方法应该是公共的,所以使用它们。

一些快速的(根据需要清理,也没有完全测试):

<?php
declare(strict_types=1);
namespace App'Entity;
use Exception;
/**
 *
 */
class DataModel
{
    /**
     * @return array
     */
    public function __toArray(): array {
        $properties = [];
        $public_methods = get_class_methods($this);
        foreach ($public_methods as $method) {
            if (str_starts_with($method, 'get')) {
                $property = lcfirst(str_replace('get', '', $method));
                try {
                    $properties[$property] = $this->$method();
                } catch (Exception $exception) {
                    //pass
                }
            }
        }
        return $properties;
    }
}

为了它的价值,我有相同的需求和斗争使用序列化器解决方案与MaxDepth的东西,所以,从其他帖子的启发,这是我的解决方案:在每个实体类中,添加一个方法来获取属性:

protected function getObjectVars(): array
{
    return get_object_vars($this);
}

在抽象性中,我所有的实体都是从抽象性中扩展出来的,添加这个方法:

public function toArray(): array
{
    $objectVar = [];
    if (method_exists($this, 'getObjectVars')) {
        $objectVar = $this->getObjectVars();
        foreach ($objectVar as &$item) {
            if ($item instanceof 'DateTime) {
                $item = $item->format('Y-m-d H:i:s');
            }
            if ($item instanceof PersistentCollection) {
                $temp = [];
                foreach ($item as $value) {
                    $temp[] = $value->getId();
                }
                $item = $temp;
            }
            if ($item instanceof self) {
                $item = $item->getId();
            }
        }
    }
    return $objectVar;
}

希望对你有帮助;)

你可以简单地使用

$demo=array($demo);