Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected return value #43

Closed
Vandersteen opened this issue Oct 5, 2017 · 5 comments
Closed

Unexpected return value #43

Vandersteen opened this issue Oct 5, 2017 · 5 comments

Comments

@Vandersteen
Copy link

Hello,

I've encountered some unexpected behaviour using UUID's and doctrine relations:

Lets say I have the 2 following classes

Car

class Car
{
    /**
     * @var Uuid
     *
     * @ORM\Id()
     * @ORM\Column(type="uuid")
     */
    private $id;

    /**
     * @var Person
     *
     * @ORM\ManyToOne(targetEntity="Person")
     */
    private $owner;

    /**
     * @return Uuid
     */
    public function getId(): Uuid
    {
        return $this->id;
    }

    /**
     * @return Person
     */
    public function getOwner(): Person
    {
        return $this->owner;
    }
}

Person

class Person
{
    /**
     * @var Uuid
     *
     * @ORM\Id()
     * @ORM\Column(type="uuid")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @return Uuid
     */
    public function getId(): Uuid
    {
        return $this->id;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }
}

Using it as follows errors with: Expected return type of UUID, string returned

$car = $this->carRepo->findOneById($id);
$car->getOwner()->getId();  /**  returns string */

The following does work

$car = $this->carRepo->findOneById($id);
$car->getOwner()->getName();
$car->getOwner()->getId();  /** returns UUID */

From what I understand, It returns a string because doctrine will create a 'proxy' with the id pre-filled until a property is accessed and the entity 'initialised'.

I could add the following in the getId() method:

 if(is_string($this->id))
 {
        $this->id = UUID::fromString($this->id);
 }

But this kinda beats the purpose of types.

So my questions are:

  • Am I missing something in the annotations ?
  • Is this a bug I should report at doctrine ?
@ramsey
Copy link
Owner

ramsey commented Oct 5, 2017

It isn’t enough to set the column type to “uuid,” since that will use Doctrine’s internal UUID generator, which is string-based. If you’d like to use ramsey/uuid, you need more annotations:

    /**
     * @Id
     * @Column(type="uuid", unique=true)
     * @GeneratedValue(strategy="CUSTOM")
     * @CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
     */

The custom strategy and generator class references are important to get Doctrine to return a Uuid object, instead of string.

@Vandersteen
Copy link
Author

I've just tried it out, changing the annotations does not fix the issue, i still get

Return value of Person::getId() must be an instance of Ramsey\Uuid\Uuid, string returned

@mcneely
Copy link
Contributor

mcneely commented Oct 5, 2017

What happens when you ditch chaining and declare owner as a variable?

@stof
Copy link

stof commented Oct 5, 2017

This is a known issue of Doctrine currently. When creating a proxy object (which is the case here for the owner), type conversions are not properly applied. This is why the id is returned as a string before initialization (it works fine after initialization due to the initialization setting all properties from the loaded data with the right type, including the id).
doctrine/orm#6719 fixes it for Doctrine 3 (which is still far from being ready) thanks to the full rewriting of the proxy layer.

@Vandersteen
Copy link
Author

Vandersteen commented Oct 5, 2017

Ok thanks for confirming @stof.

@ramsey ramsey closed this as completed Apr 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants