【问题标题】:Doctrine: Convert array to Doctrine entity教义:将数组转换为教义实体
【发布时间】:2013-11-27 22:18:16
【问题描述】:

我正在寻找一种将数组转换为学说实体的方法。我正在使用学说 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 表单发布数据时,我想将发布数组转换为用户实体。所以我有一个像

这样的数组
$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 arrays doctrine-orm


    【解决方案1】:

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

    扩展存储库

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

    用法,你的repo中的一个方法:

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

    【讨论】:

      【解决方案2】:

      为什么不编写您的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;
      }
      

      【讨论】:

      • 我在 User 类中还有其他一些不是字符串的变量。所以我一直在寻找一种方法来从注释中获取信息以保持其通用性。就像我在 $date 字段上将 @var DateTime 作为注释一样。
      • @Rifat A @var doc 注释只是 IDE 的类型提示。我会为任何需要的转换使用适当的设置器
      【解决方案3】:

      您正在尝试反序列化

      我会查看Zend Framework 2 Stdlib component。您不需要使用整个框架。

      Hydrators,特别是DoctrineModule\Stdlib\Hydrator\DoctrineObject,按照您的要求去做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-02
        • 2018-09-06
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多