DDC-1379: Entity Generator Bug with extended classes #1725

Closed
opened 2026-01-22 13:23:26 +01:00 by admin · 7 comments
Owner

Originally created by @doctrinebot on GitHub (Sep 16, 2011).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user mbadolato:

I'm presently using Doctrine 2 in conjunction with Symfony 2 and have come across a bug with the Entity Generator when I'm extending an abstract class. Here's a minor example to demonstrate (please note, any annotations problems or typos are a result of my typing in this ticket. This isn't an actual example, but does accurately show how to reproduce the issue)

abstract class Foo
{
    /****
     * @Column(name="first_name")
     */
    protected $firstName;

     /****
     * @Column(name="last_name")
     */
    protected $lastName;
    /****
     * @ORM\Column(name="is_active", type="boolean")
     */
    protected $isActive;
}
/****
 * @Entity
 */
class Bar extends Foo
{
    /****
     * @Id
     * @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /****
     * @Column(name="created_at", type="datetime")
     */
    protected $createdAt;
}

Using a setup similar to the above, where Bar extends Foo, there is an issue with the Generator.

  1. The generator is redeclaring Foo's properties, as private variables, in Bar

So, opening Bar after running the generator, shows the getters and setters, but shows:
private $firstName;
private $lastName;
private $isActive;

This causes issues because the properties are being recreated as local versions, and their scope is set to private, conflicted with the more open protected version in the abstract class. To me, they shouldn't be placed in Bar because they're declared as protected in Foo and thus Bar has access to them. Also, when they are placed in Bar, the file formatting is messed up around them, suggesting that they were mis-placed in the file.

  1. This may or may not be a bug (it may be intended behavior), but... I would think that when running the generator, the getters and setters for the protected properties declared in Foo would be placed in Foo, and not placed in the class(es) that extend Foo (in this case, Bar). If I also have a class Baz that extends Foo, then Bar and Baz will now have copies of the same getFirstName(), getLastName(), and getIsActive() methods, which is unneeded. They can be placed in the parent class, and overridden in the subclasses if more/different functionality/behavior is needed by the subclass.

Hopefully this is a clear example. Please feel free to hit me up for more info!
--mark

Originally created by @doctrinebot on GitHub (Sep 16, 2011). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user mbadolato: I'm presently using Doctrine 2 in conjunction with Symfony 2 and have come across a bug with the Entity Generator when I'm extending an abstract class. Here's a minor example to demonstrate (please note, any annotations problems or typos are a result of my typing in this ticket. This isn't an actual example, but does accurately show how to reproduce the issue) ``` abstract class Foo { /**** * @Column(name="first_name") */ protected $firstName; /**** * @Column(name="last_name") */ protected $lastName; /**** * @ORM\Column(name="is_active", type="boolean") */ protected $isActive; } ``` ``` /**** * @Entity */ class Bar extends Foo { /**** * @Id * @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ protected $id; /**** * @Column(name="created_at", type="datetime") */ protected $createdAt; } ``` Using a setup similar to the above, where Bar extends Foo, there is an issue with the Generator. 1) The generator is redeclaring Foo's properties, as private variables, in Bar So, opening Bar after running the generator, shows the getters and setters, but shows: private $firstName; private $lastName; private $isActive; This causes issues because the properties are being recreated as local versions, and their scope is set to private, conflicted with the more open protected version in the abstract class. To me, they shouldn't be placed in Bar because they're declared as protected in Foo and thus Bar has access to them. Also, when they are placed in Bar, the file formatting is messed up around them, suggesting that they were mis-placed in the file. 2) This may or may not be a bug (it may be intended behavior), but... I would think that when running the generator, the getters and setters for the protected properties declared in Foo would be placed in Foo, and not placed in the class(es) that extend Foo (in this case, Bar). If I also have a class Baz that extends Foo, then Bar and Baz will now have copies of the same getFirstName(), getLastName(), and getIsActive() methods, which is unneeded. They can be placed in the parent class, and overridden in the subclasses if more/different functionality/behavior is needed by the subclass. Hopefully this is a clear example. Please feel free to hit me up for more info! --mark
admin added the Bug label 2026-01-22 13:23:26 +01:00
admin closed this issue 2026-01-22 13:23:26 +01:00
Author
Owner

@doctrinebot commented on GitHub (Oct 30, 2011):

Comment created by cvschaefer:

I can confirm this behavior.

Before generation:

/****
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 *
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({"foo_bar" = "FooBar"})
 */
class Foo
{

    /****
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /****
     * creation date
     *
     * @ORM\Column(name="created_at",type="datetime")
     */
    protected $createdAt;

    /****
     * getCreatedAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /****
     * Set the creation date
     *
     * @return null
     */
    public function setCreatedAt(\DateTime $createdAt)
    {
        $this->createdAt = $createdAt;
    }

    /****
     * @ORM\PrePersist
     */
    public function prePersist()
    {
        $this->createdAt = new \DateTime();
    }
}
/****
 * @ORM\Entity
 */
class FooBar extends Foo {

    /****
     *
     * @ORM\Column(type="string", length=255)
     */
    protected $title;
}

after generation of FooBar:

/****
 * @ORM\Entity
 */
class FooBar extends Foo {

    /****
     *
     * @ORM\Column(type="string", length=255)
     */
    protected $title;

    /****
     * @var integer $id
     */
    private $id;

    /****
     * @var datetime $createdAt
     */
    private $createdAt;

    /****
     * Set title
     *
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /****
     * Get title
     *
     * @return string 
     */
    public function getTitle()
    {
        return $this->title;
    }

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

    /****
     * Set createdAt
     *
     * @param datetime $createdAt
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;
    }

    /****
     * Get createdAt
     *
     * @return datetime 
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }
}

It looks like the generator doesn't check if an attribute is inherited and therefore is already defined.
If an attribute is found as inherited, the generation of the attribute, accessor and mutator should be skipped.

This bug is really annoying, especially when working with bigger objects.

Tested within Symfony2 v2.0.4

doctrine-common]
    git=http://github.com/doctrine/common.git
    version=2.1.2

[doctrine-dbal]
    git=http://github.com/doctrine/dbal.git
    version=2.1.3

[doctrine]
    git=http://github.com/doctrine/doctrine2.git
    version=2.1.2

-Chris

@doctrinebot commented on GitHub (Oct 30, 2011): Comment created by cvschaefer: I can confirm this behavior. Before generation: ``` /**** * @ORM\Entity * @ORM\HasLifecycleCallbacks * * @ORM\InheritanceType("JOINED") * @ORM\DiscriminatorColumn(name="discr", type="string") * @ORM\DiscriminatorMap({"foo_bar" = "FooBar"}) */ class Foo { /**** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /**** * creation date * * @ORM\Column(name="created_at",type="datetime") */ protected $createdAt; /**** * getCreatedAt * * @return \DateTime */ public function getCreatedAt() { return $this->createdAt; } /**** * Set the creation date * * @return null */ public function setCreatedAt(\DateTime $createdAt) { $this->createdAt = $createdAt; } /**** * @ORM\PrePersist */ public function prePersist() { $this->createdAt = new \DateTime(); } } ``` ``` /**** * @ORM\Entity */ class FooBar extends Foo { /**** * * @ORM\Column(type="string", length=255) */ protected $title; } ``` after generation of FooBar: ``` /**** * @ORM\Entity */ class FooBar extends Foo { /**** * * @ORM\Column(type="string", length=255) */ protected $title; /**** * @var integer $id */ private $id; /**** * @var datetime $createdAt */ private $createdAt; /**** * Set title * * @param string $title */ public function setTitle($title) { $this->title = $title; } /**** * Get title * * @return string */ public function getTitle() { return $this->title; } /**** * Get id * * @return integer */ public function getId() { return $this->id; } /**** * Set createdAt * * @param datetime $createdAt */ public function setCreatedAt($createdAt) { $this->createdAt = $createdAt; } /**** * Get createdAt * * @return datetime */ public function getCreatedAt() { return $this->createdAt; } } ``` It looks like the generator doesn't check if an attribute is inherited and therefore is already defined. If an attribute is found as inherited, the generation of the attribute, accessor and mutator should be skipped. This bug is really annoying, especially when working with bigger objects. Tested within Symfony2 v2.0.4 ``` doctrine-common] git=http://github.com/doctrine/common.git version=2.1.2 [doctrine-dbal] git=http://github.com/doctrine/dbal.git version=2.1.3 [doctrine] git=http://github.com/doctrine/doctrine2.git version=2.1.2 ``` -Chris
Author
Owner

@doctrinebot commented on GitHub (Jan 9, 2012):

Comment created by @beberlei:

As per the help message of the entity generation inheritance generation is not yet supported and will not work.

Its planned for 2.3.

Follow DDC-1590 for current information.

@doctrinebot commented on GitHub (Jan 9, 2012): Comment created by @beberlei: As per the help message of the entity generation inheritance generation is not yet supported and will not work. Its planned for 2.3. Follow [DDC-1590](http://www.doctrine-project.org/jira/browse/DDC-1590) for current information.
Author
Owner

@doctrinebot commented on GitHub (Jan 9, 2012):

Issue was closed with resolution "Duplicate"

@doctrinebot commented on GitHub (Jan 9, 2012): Issue was closed with resolution "Duplicate"
Author
Owner

@doctrinebot commented on GitHub (Aug 5, 2014):

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1098] was assigned:
https://github.com/doctrine/doctrine2/pull/1098

@doctrinebot commented on GitHub (Aug 5, 2014): Comment created by @doctrinebot: A related Github Pull-Request [GH-1098] was assigned: https://github.com/doctrine/doctrine2/pull/1098
Author
Owner

@doctrinebot commented on GitHub (Aug 18, 2014):

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1098] was closed:
https://github.com/doctrine/doctrine2/pull/1098

@doctrinebot commented on GitHub (Aug 18, 2014): Comment created by @doctrinebot: A related Github Pull-Request [GH-1098] was closed: https://github.com/doctrine/doctrine2/pull/1098
Author
Owner

@doctrinebot commented on GitHub (Dec 28, 2014):

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1231] was assigned:
https://github.com/doctrine/doctrine2/pull/1231

@doctrinebot commented on GitHub (Dec 28, 2014): Comment created by @doctrinebot: A related Github Pull-Request [GH-1231] was assigned: https://github.com/doctrine/doctrine2/pull/1231
Author
Owner

@doctrinebot commented on GitHub (Jan 17, 2015):

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1231] was merged:
https://github.com/doctrine/doctrine2/pull/1231

@doctrinebot commented on GitHub (Jan 17, 2015): Comment created by @doctrinebot: A related Github Pull-Request [GH-1231] was merged: https://github.com/doctrine/doctrine2/pull/1231
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#1725