Moinul Hossain
Moinul Hossain

Reputation: 2206

Doctrine: Convert array to Doctrine entity

I am looking for a way to convert an array to doctrine Entity. I am using doctrine 2.

I have an entity class like:

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
}

When I post data from a html form, I want to convert the post array to the User entity. So I have an array like

$userAsArray = array("email"=>"[email protected]","password"=>"hello","dob"=>"10\20\1990");

$user = new User();

covert($userAsArray,$user) // I am looking for something like this

I am looking for a generic way to accomplish this. I have tried 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;
    }

But the problem is it sets everything as string. But for the date I want to have it as a DateTime object. Any help?

Upvotes: 2

Views: 10722

Answers (3)

AlexP
AlexP

Reputation: 9857

You are trying to de-serialize

I would check out the Zend Framework 2 Stdlib component. You do not need to use the whole framework.

The Hydrators, specifically the DoctrineModule\Stdlib\Hydrator\DoctrineObject, do what you are asking.

Upvotes: 0

b.b3rn4rd
b.b3rn4rd

Reputation: 8840

what if one of your array elements is a foreign key ? before setting entity properties, you might need to prepare foreign key attributes. This is how I accomplish similar task:

Extend Repository

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

Create parent Entity class :

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

Usage, a method in your repo:

$entity = new User();
$attributes = array(
    "email"    =>"[email protected]",
    "password" =>"hello",
    "dob"      =>"10\20\1990"));
$entity->fromArray($this->prepareAttributes($attributes));
$this->getEntityManager()->persist($entity);
$this->getEntityManager()->flush();    

Upvotes: 6

Phil
Phil

Reputation: 164970

Why not write your setDob() method to detect a string and convert it if necessary

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

Upvotes: 1

Related Questions