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

Support Embeddables #2

Open
klkvsk opened this issue Feb 26, 2024 · 4 comments
Open

Support Embeddables #2

klkvsk opened this issue Feb 26, 2024 · 4 comments

Comments

@klkvsk
Copy link

klkvsk commented Feb 26, 2024

#[ORM\Embedded]
protected MyEmbed $obj;

Results in:

In EntityGenerator.php line 114:
Warning: Undefined array key "obj"

It seems that embeddables are not supported currently, but neither are they skipped, and it fails here:

if ($metadata->hasField($property)) {
$this->addField($request, $metadata->fieldMappings[$property]);
} elseif ($metadata->hasAssociation($property)) {

because hasField is:
return isset($this->fieldMappings[$fieldName]) || isset($this->embeddedClasses[$fieldName])

hlecorche added a commit to hlecorche/doctrine-entities-generator-bundle that referenced this issue Feb 27, 2024
@hlecorche
Copy link
Contributor

Thank you for identifying this issue. I've created a commit to fix the problem. You can test the solution on the master branch. If everything checks out, I'll proceed with publishing a stable version right after.

Feel free to provide any feedback or further observations.

Thanks again for your contribution to improving the project.

@klkvsk
Copy link
Author

klkvsk commented Mar 11, 2024

Updated to dev version and it generated correct code for embeddables' access methods. Everything seems great so far, thank you!

@klkvsk
Copy link
Author

klkvsk commented Mar 11, 2024

One issue I found is sometimes we need to initialize embeddable property in entity's constructor:
https://www.doctrine-project.org/projects/doctrine-orm/en/3.1/tutorials/embeddables.html#initializing-embeddables

It can depend from case to case, but I think if property is not nullable, and embeddable's constructor does not have any arguments, it's instantiation can be safely added to entity's __construct:

#[ORM\Embeddable]
class MyEmbed 
{
    /// ... properties ...

    public function __construct() // or no __construct at all
    {
        // no args - so we can generate new-statement safely
    }
}

#[ORM\Entity]
class MyEntity 
{
    #[ORM\Embedded]
    private MyEmbed $embed; // not nullable - it SHOULD be initialized within __construct

    /*
     * Getters / Setters (auto-generated)
     */

    public function __construct() 
    {
        $this->embed = new MyEmbed(); 
    }
    /// ... getters / setters ...
}

That raises further question, though: what if MyEmbed::__construct has optional arguments? Then we can not be 100% sure that it should be instantiated without them.

Normally, one would need to use EntityInitializerInterface to initialize the embeddable manually if they have to pass constructor args to it. So we can probably use this fact to decide do we put it the constructor or not.

So my current suggestion is, while rendering entity's __construct method:

  • A) If embeddable's property is non-nullable
  • B) And it's holding entity does not implement EntityInitializerInterface
  • C) And embeddable's constructor have no required arguments

then output $this->embed = new MyEmbed() in __construct()

If it is only A and B, but there are required arguments, would be nice to emit a warning: "{propertyName} is missing an initializer".

In all other cases, omit the initializer.


PS. This is kinda opinionated, I know -- this feature is not critical, and developer can always use initilizeEntity whenever they have a required embeddable in their entity. And I did it like this too, for now. But knowing that it CAN be autogenerated bugs me a bit :) Probably would be better to get second opinion on that, but that was my 2 cents.

@klkvsk
Copy link
Author

klkvsk commented Mar 11, 2024

Another issue: trying to convert an embeddable class itself to generated methods, getting "No class found".
Does it check that class is marked with Entity attribute, maybe? Doctrine should have metadata available for embeddables as well as for entities, I guess...

On a side note, I had "No class found" also when trying to generate methods for a trait, that is used to hold a common set of fields for two different entities (can not use class inheritance there). Would be nice to fix this too.

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

2 participants