条令:将数组转换为条令实体


Doctrine: Convert array to Doctrine entity

我正在寻找一种将数组转换为条令实体的方法。我使用的是教义2。

我有一个实体类,比如:

class User
{

    /**
     * @Id
     * @Column(type="integer", nullable=false)
     * @GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @Column(type="string", length=255, unique=true, nullable=false)
     */
    protected $email;
    /**
     * @Column(type="string", length=64, nullable=false)
     */
    protected $password;
    /**
     * @var DateTime
     * @Column(type="datetime", nullable=false)
     */
    protected $dob;
    //getter and setters
}

当我从html表单发布数据时,我想将post数组转换为User实体。所以我有一个类似的阵列

$userAsArray = array("email"=>"abc@xyz.com","password"=>"hello","dob"=>"10'20'1990");
$user = new User();
covert($userAsArray,$user) // I am looking for something like this

我正在寻找一种通用的方法来实现这一点。我试过这样的东西:

 function fromArray(array $array,$class){
        $user = new $class();
        foreach($array as $key => $field){
            $keyUp = ucfirst($key);
            if(method_exists($user,'set'.$keyUp)){
                call_user_func(array($user,'set'.$keyUp),$field);
            }
        }
        return $user;
    }

但问题是,它将所有内容都设置为字符串。但对于日期,我希望将其作为DateTime对象。有什么帮助吗?

如果您的数组元素之一是外键怎么办?在设置实体属性之前,您可能需要准备外键属性。这就是我完成类似任务的方式:

扩展存储库

<?php
namespace My'Doctrine;
use Doctrine'ORM'EntityRepository;
class Repository extends EntityRepository
{
    /**
     * Prepare attributes for entity 
     * replace foreign keys with entity instances
     * 
     * @param array $attributes entity attributes
     * @return array modified attributes values 
     */
    public function prepareAttributes(array $attributes)
    {
        foreach ($attributes as $fieldName => &$fieldValue) {
            if (!$this->getClassMetadata()->hasAssociation($fieldName)) {
                continue;
            }
            $association = $this->getClassMetadata()
                ->getAssociationMapping($fieldName);
            if (is_null($fieldValue)) {
                continue;
            }
            $fieldValue = $this->getEntityManager()
                ->getReference($association['targetEntity'], $fieldValue);
            unset($fieldValue);    
        }
        return $attributes;
    }
}

创建父Entity类:

namespace My'Doctrine;
class Entity
{
    /**
     * Assign entity properties using an array
     * 
     * @param array $attributes assoc array of values to assign
     * @return null 
     */
    public function fromArray(array $attributes)
    {
        foreach ($attributes as $name => $value) {
            if (property_exists($this, $name)) {
                $methodName = $this->_getSetterName($name);
                if ($methodName) {
                    $this->{$methodName}($value);
                } else {
                    $this->$name = $value;
                }
            }
        }
    }
    /**
     * Get property setter method name (if exists)
     * 
     * @param string $propertyName entity property name
     * @return false|string 
     */
    protected function _getSetterName($propertyName)
    {
        $prefixes = array('add', 'set');
        foreach ($prefixes as $prefix) {
            $methodName = sprintf('%s%s', $prefix, ucfirst(strtolower($propertyName)));
            if (method_exists($this, $methodName)) {
                return $methodName;
            }
        }
        return false;
    }
}

用途,回购中的一种方法:

$entity = new User();
$attributes = array(
    "email"    =>"abc@xyz.com",
    "password" =>"hello",
    "dob"      =>"10'20'1990"));
$entity->fromArray($this->prepareAttributes($attributes));
$this->getEntityManager()->persist($entity);
$this->getEntityManager()->flush();    

为什么不编写setDob()方法来检测字符串,并在必要时进行转换

public function setDob($dob) {
    if (!$dob instanceof DateTime) {
        $dob = new DateTime((string) $dob); // or however you want to do the conversion
    }
    $this->dob = $dob;
}

您正在尝试反序列化

我将查看Zend Framework 2 Stdlib组件。您不需要使用整个框架。

水合物,特别是DoctrineModule''Stdlib''Hydrator''DoctrineObject,按照您的要求执行。