5

I working with zf2.1.3 and doctrine 2. I was trying to hydrate information on my class and realize that the DoctrineModule\Stdlib\Hydrator\DoctrineObject doesn't work with fields that have underline on it, like cat_id.

Here an example:

/* namespace Application\Entity; */

class Foo
{
    private $cat_id;
    private $cat_name;

    public function getCatId()
    {
        return $this->cat_id;
    }

    public function setCatName($name)
    {
        $this->cat_name = $name;
        return $this;
    }

    public function getCatName()
    {
        return $this->cat_nome;
    }
}

class Bar
{
    private $id;
    private $name;

    public function getId()
    {
        return $this->id;
    }

    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    public function getName()
    {
        return $this->nome;
    }
}

/* namespace Application\Controller; */

use \DoctrineModule\Stdlib\Hydrator\DoctrineObject;
public function indexAction()
{
    $hydrator = new DoctrineObject($this->getEntityManager(), 'Application\Entity\Foo');
    $foo = $hydrator->hydrate(array('cat_name' => 'Frank Moraes'), new Foo());
    \Zend\Debug\Debug::dump($foo, 'Foo Hydrator');

    $hydrator = new DoctrineObject($this->getEntityManager(), 'Application\Entity\Bar');
    $bar = $hydrator->hydrate(array('name' => 'Frank Moraes'), new Bar());
    \Zend\Debug\Debug::dump($inscrit, 'Bar Hydrator');
}

This code returns the following:

Foo Hydrator
object(Application\Entity\Foo)
    private 'cat_id' => null
    private 'cat_name' => null

Bar Hydrator
object(Application\Entity\Foo)
    private 'id' => null
    private 'name' => 'Frank Moraes'

So my question is: Why Doctrine Hydrator doesn't work with fields that have underline in it? How can I make this work?

Thank you!

Edited

Sorry for the long time with no answer. A have no access to SO on my work!

I tried the following:

$hydrator = new DoctrineObject($this->getEntityManager(), 'Application\Entity\Foo', false);

For the example I posted here, this false parameter works fine.

But, it didn't work when I'm binding the class on a form!

Someone have a clue?

Vinicius Garcia
  • 1,740
  • 4
  • 30
  • 54
  • I'd post this question on the Doctrine Users Google group. – Peter Wooster Mar 11 '13 at 01:31
  • That's because the default inflector doesn't handle underscores. You need to tweak it on your own or post an issue on the issue tracker of doctrine module at https://github.com/doctrine/DoctrineModule/issues I can tell you right now that I don't have time to look into it right now though. – Ocramius Mar 11 '13 at 03:05
  • I posted the issue on https://github.com/doctrine/DoctrineModule/issues/190 – Vinicius Garcia Mar 13 '13 at 01:14

3 Answers3

9

Several months after this has been asked, but I've been checking the source code of the DoctrineObject hydrator just now, and I think this is what's going on:

By default, unless you construct the DoctrineObject hydrator with the byValue flag as false, the hydrator will work in byValue mode. What that means is that it tries to construct getter and setter method names from the values that you're trying to hydrate, and the way it does that is by calling ucfirst on the field name and prepending get/set to that.

So, for instance, you have cat_name, so it will try the getter method getCat_name which clearly is incorrect.

You have 4 choices, then:

  • A: camelCase your variable names
  • B: Set byValue to false (so that it tries to access the variables directly) [although I think you might have to make the variables public in that case... I'm not sure how visibility will affect it, as I haven't tried it before]
  • C: Use a different hydration Strategy or
  • D: Just have weird getter and setter names like getCat_name (please don't do this).
edigu
  • 9,878
  • 5
  • 57
  • 80
osdiab
  • 1,972
  • 3
  • 26
  • 37
  • 2
    Thanks for posting this! I'd solved this by changing my variable names to camelCase. Good to know the reason of this problem! – Vinicius Garcia Oct 07 '13 at 20:14
  • For option **B** you shouldn't set the properties to public because it will [break lazy loading](http://stackoverflow.com/questions/4090609/how-can-public-fields-break-lazy-loading-in-doctrine-2). If you want access to your properties without getters and setters you should implement [magic `__get` and `__set`](http://php.net/manual/en/language.oop5.magic.php) – Wilt Mar 07 '15 at 15:22
  • for option **B** protected and private properties will be filled, it uses reflection and ignores access methods (getters and setters) and access modifiers (protected and private) – NDM Apr 02 '15 at 11:38
  • Thank you. Using a Framework like ZF2 where the ClassMethods hydrator works differently, this sent me for a 30 minute loop. – Saeven Jul 03 '15 at 20:28
0

Quick and dirty...

foreach ($form as $key => $value) {
        while ($pos = strrpos($key,'_')) {                                  
            $key = substr_replace($key, '', $pos, 1);
            $capitalized = strtoupper($key[$pos]);
            $key[$pos] = $capitalized;                                
        }
        $data[$key] = $value;
    }
talisker
  • 53
  • 7
0

You can still use this trick:

/** @ORM\Column(name="column_name", type="string") */
protected $columnName;

function get(...);
function set($columnName){$this->columnName = $columnName}

Hope helps

Webdesign7 London
  • 775
  • 1
  • 8
  • 14