Question

How should I annotate inheritance to be able to find a subclass? My current annotations:

<?php
// Product.php
namespace Entity;

/**
 * @Entity @Table(name="products")
 **/
class Product
{
    /**
     * @var int
     * @Id @Column(type="integer") @GeneratedValue
     */
    protected $id;
}


<?php
namespace Entity;
// Coffee.php
/**
 * @Entity
 */
class Coffee extends Product
{
    protected $taste;    
}

It works like a charm when I persist new entities, but fail to fetch an existent entity by Id

$entityManager->find('Entity\\Coffee', 1)

with error:

Column not found: 1054 Unknown column 't0.id' in 'where clause'

I cannot use MappedSuperclass for Products.


UPDATE:

Product::taste is not a database column. It is a POPO field. I must confuse myself with Doctrine ORM inheritance, which aims to extend model to persist extra data for extended entities. In my case the child class has no extra columns, but rather defines different behaviour of the base class. Furthermore, both are mutually interchangeable, so I expect

$coffee = new Entity\Coffee();
$entityManager->persist($coffee);
$entityManager->flush();

/* @var Entity\Product $product */
$product = $entityManager->find('Entity\\Product', $coffee->getId());

/* @var Entity\Coffee $coffee */
$coffee = $entityManager->find('Entity\\Coffee', $product->getId());

It seems I don't really need ORM inheritance, but just hydration of data from products table into either base or child objects. Not sure if it possible though.

No correct solution

OTHER TIPS

You need to supply InheritanceType, DiscriminatorMap, and DiscriminatorColumn on the superclass to correctly map the inheritance relationship. It will add exactly one extra column to the table (the one you specify in DiscriminatorColumn).

A temporary workaround I have found so far is to use single table inheritance advised by @bspellmeyer and @timdev with dynamic mapping:

use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadata;

class ProductEntityListener
{
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $metadata = $eventArgs->getClassMetadata();
        if (in_array($metadata->getName(), [
            'Entity\Coffee',
            'Entity\Product'
        ])) {
            $metadata->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
            $metadata->setDiscriminatorColumn(['name' => 'discr', 'type' => 'string', 'length' => 3]);
            $metadata->addDiscriminatorMapClass('all', $metadata->getName());
            $metadata->subClasses = [];
        }
    }
} 

Although it does the job I don't mark it as a correct answer because it still requires an extra meaningless column discr which contains 'all' for all rows and is is rather a hack. I wonder if there is a proper solution to extend Entity class without extending ORM model.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top