Symfony - how to make Doctrine search in abstract mapped superclass?

Viewed 1143

I am building an online shop for plastic model makers (hence the 'model').

I have a Product mapped superclass because I want all products (models, tools, paints etc. to have name, price and description):

<?php    
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\MappedSuperclass;
use Gedmo\Mapping\Annotation as Gedmo; // gedmo annotations

/** @MappedSuperclass */
abstract class Product
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     * @ORM\Column(type="string", length=100, nullable=false)
     */
    protected $name;

    /**
     * @var int
     * @ORM\Column(type="decimal", scale=2, nullable=false)
     */
    protected $price;

    /**
     * @var string
     * @ORM\Column(type="text", nullable=true)
     */
    protected $description;

    /**
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    /**
     * @ORM\Column(type="datetime")
     * @Gedmo\Timestampable(on="update")
     */
    private $updatedAt;

    //getters and setters...

}

Then, there's a Model class, for plastic models, this extends the Product class but also has a Category for being able to search from cars, aircraft, ships etc:

<?php    
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="model")
 */
class Model extends Product
{

    /**
     * @var Category
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="models")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=true)
     */
    private $category;

    /**
     * @return Category
     */
    public function getCategory()
    {
        return $this->category;
    }

    /**
     * @param Category $category
     */
    public function setCategory($category)
    {
        $this->category = $category;
    }


}

There will of course be more classes extending Product mapped superclass. Now I want to select the 10 most recently added products, regardless of their kind (models, tools, paints).

How can I tell Doctrine to give me the last 10 added products? Of course I tried something like: $this->getDoctrine()->getManager()->getRepository("AppBundle:Product");

but of course it throws an exception saying that

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'modeller_app.product' doesn't exist

which obviously is true, because Product is an abstract class and not actually an entity. How can I solve this problem?

1 Answers

You need to use class table inheritance.

Here is a example:

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"product" = "Product", "model" = "Model"})
 */
class Product
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(type="string", length=100, nullable=false)
     */
    protected $name;

    ...
}

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */
class Model extends Product
{
    // Custom properties

    ...
}

Now you can query the Product entity and it will return the result from all entities that inherits it.

Related