想要将学说实体对象转换为普通数组,这是我目前为止的代码,
$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);