cb0
cb0

Reputation: 8613

Doctrine2 Migration - single table inheritance - parent id does not exist

I don't get a simple table inheritance to work in my blog.

Here is what I have:

3 simple classes

  1. A general abstract Comment Class
  2. Subclass for comments made to blog posts with a foreign key to one
  3. Subclass for comments on activities also with an foreign key

General Comment Entity

/**
 * @ORM\MappedSuperClass
 * @ORM\Entity(repositoryClass="MY\BlogBundle\Entity\Repository\CommentRepository")
 * @ORM\Table(name="blog_comment")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap( {"blogentry" = "BlogComment", "activity" = "ActivityComment"} )
 * @ORM\HasLifecycleCallbacks
 */
abstract class Comment
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="title", type="string", length=255, nullable=true)
     * @Assert\NotBlank()
     */
    private $title;
    ...

Comment for Blog

/**
 * BlogEntryComment
 * @ORM\Entity(repositoryClass="MY\BlogBundle\Entity\Repository\BlogEntryCommentRepository")
 */
class BlogComment extends Comment
{

/**
 * @ORM\ManyToOne(targetEntity="MY\BlogBundle\Entity\BlogEntry", inversedBy="comments")
 * @ORM\JoinColumn(name="blog_entry_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
 */
 private $blogEntry;
 ...

Comment for Activity

/**
 * @ORM\Entity(repositoryClass="MY\BlogBundle\Entity\Repository\ActivityCommentRepository")
 */
class ActivityComment extends Comment
{
/**
 * @ORM\ManyToOne(targetEntity="MY\BlogBundle\Entity\Activity", inversedBy="comments")
 * @ORM\JoinColumn(name="activity_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
 */
 private $activity;
 ...

Building all entities with

./app/console doctrine:generate:entities MY

works fine, this means that super class methods like getId() will be automatically be inserted into Comment class.

And the only functions inside sub-classes are setter and getter for their own properties like getBlogEntry() or getActivity()

When I finally try to create a migration to update the database I get:

    ./app/console doctrine:migrations:diff -vvv                                                        

  [ReflectionException]                                                    
  Property MY\BlogBundle\Entity\ActivityComment::$id does not exist  

Exception trace:
 () at MY_PATH/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php:79
 ReflectionProperty->__construct() at MY_PATH/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php:79
 Doctrine\Common\Persistence\Mapping\RuntimeReflectionService->getAccessibleProperty() at MY_PATH/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php:889
 Doctrine\ORM\Mapping\ClassMetadataInfo->wakeupReflection() at MY_PATH/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:537
 Doctrine\ORM\Mapping\ClassMetadataFactory->wakeupReflection() at MY_PATH/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php:209
 Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor() at MY_PATH/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php:114
 Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getAllMetadata() at MY_PATH/vendor/doctrine/migrations/lib/Doctrine/DBAL/Migrations/Tools/Console/Command/DiffCommand.php:68
 Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand->execute() at MY_PATH/vendor/doctrine/doctrine-migrations-bundle/Doctrine/Bundle/MigrationsBundle/Command/MigrationsDiffDoctrineCommand.php:49
 Doctrine\Bundle\MigrationsBundle\Command\MigrationsDiffDoctrineCommand->execute() at MY_PATH/vendor/symfony/console/Symfony/Component/Console/Command/Command.php:252
 Symfony\Component\Console\Command\Command->run() at MY_PATH/vendor/symfony/console/Symfony/Component/Console/Application.php:900
 Symfony\Component\Console\Application->doRunCommand() at MY_PATH/vendor/symfony/console/Symfony/Component/Console/Application.php:192
 Symfony\Component\Console\Application->doRun() at MY_PATH/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:96
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at MY_PATH/vendor/symfony/console/Symfony/Component/Console/Application.php:123
 Symfony\Component\Console\Application->run() at MY_PATH/app/console:22

It will not find the id attribute of the sub class for some reasons.

Changing access levels resulted in faulty code creation. If is set $id to public or protected will break the code generation using task ./app/console doctrine:generate:entities MY

I know there have been numerous posts about this topic but nothing helped with my problem. I did:

Can someone point me to my problem or knows what could possibly causes this. I lost a whole workday on this disgusting problem.

Upvotes: 4

Views: 2561

Answers (1)

ozahorulia
ozahorulia

Reputation: 10084

Okay, first of all you must understand, that setting $id to protected is the only correct solution. That's all.

Doctrine is generating duplicate private $id in all child classes, that's true. I had the same issue in my doctrine mongodb project. And as far as I understand it's doctrine bug, and you can nothing to do with that.

You can only remove all extra fields and methods that doctrine generates in child classes after every generate:entities command run.

Upvotes: 4

Related Questions