Found a solution on my own. The following are the various steps that I have taken. This answer is very large, but I tried to be as complete as possible.
The most important things are in the inheritanceType: JOINED YAML files inheritanceType: JOINED , discriminatorColumn: discriminatorMap: and the Video and Car class Video extends Product object classes class Video extends Product , class Car extends Product .
1) DB schema
CREATE TABLE IF NOT EXISTS `artists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `brands` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `cars` ( `id` int(11) NOT NULL, `model` varchar(255) NOT NULL, `release_date` date NOT NULL, `brand_id` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `products` ( `id` int(11) NOT NULL AUTO_INCREMENT, `description` varchar(255) NOT NULL, `price` double NOT NULL, `object_type` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `videos` ( `id` int(11) NOT NULL, `file_name` varchar(255) NOT NULL, `release_date` date NOT NULL, `artist_id` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;
2) Doctrine YAML files (from which you need to create Entity and proxy classes)
Entities.Artist.dcm.yml
Entities\Artist: type: entity table: artists id: id: type: integer primary: true notnull: true generator: strategy: AUTO fields: name: type: string(255) notnull: true oneToMany: videos: targetEntity: Video mappedBy: artist options: charset: utf8 type: InnoDB
Entities.Brand.dcm.yml
Entities\Brand: type: entity table: brands id: id: type: integer primary: true notnull: true generator: strategy: AUTO fields: name: type: string(255) notnull: true oneToMany: cars: targetEntity: Car mappedBy: brand options: charset: utf8 type: InnoDB
Entities.Car.dcm.yml
Entities\Car: type: entity table: cars fields: model: type: string notnull: true release_date: type: date notnull: true oneToOne:
Entities.Product.dcm.yml
Entities\Product: type: entity table: products id: id: type: string primary: true notnull: true generator: strategy: AUTO fields: description: type: string(255) notnull: true price: type: decimal notnull: true inheritanceType: JOINED discriminatorColumn: name: object_type type: string length: 255 discriminatorMap: video: Video car: Car options: charset: utf8 type: InnoDB
Entities.Video.dcm.yml
Entities\Video: type: entity table: videos fields: file_name: type: string notnull: true release_date: type: date notnull: true oneToOne:
3) Create Entity and Proxy classes
I am using CodeIgniter. I used the excellent guide Joel Verhagen
!! It is important that you expand the video and the car with the product - see below!
This leads to the following Entity classes
Artist.php
namespace Entities; use Doctrine\ORM\Mapping as ORM; class Artist { private $id; private $name; private $videos; public function __construct() { $this->videos = new \Doctrine\Common\Collections\ArrayCollection(); } public function getId() { return $this->id; } public function setName($name) { $this->name = $name; return $this; } public function getName() { return $this->name; } public function addVideo(\Entities\Video $videos) { $this->videos[] = $videos; } public function getVideos() { return $this->videos; } }
Brand.php
namespace Entities; use Doctrine\ORM\Mapping as ORM; class Brand { private $id; private $name; private $cars; public function __construct() { $this->cars = new \Doctrine\Common\Collections\ArrayCollection(); } public function getId() { return $this->id; } public function setName($name) { $this->name = $name; return $this; } public function getName() { return $this->name; } public function addCar(\Entities\Car $cars) { $this->cars[] = $cars; } public function getCars() { return $this->cars; } }
Car.php
namespace Entities; use Doctrine\ORM\Mapping as ORM; class Car extends Product //Important that Car extends Product { private $model; private $release_date; private $brand; public function setModel($model) { $this->model = $model; return $this; } public function getModel() { return $this->model; } public function setReleaseDate($releaseDate) { $this->release_date = $releaseDate; return $this; } public function getReleaseDate() { return $this->release_date; } public function setBrand(\Entities\Brand $brand = null) { $this->brand = $brand; return $this; } public function getBrand() { return $this->brand; } }
product.php
namespace Entities; use Doctrine\ORM\Mapping as ORM; class Product { private $id; private $description; private $price; public function getId() { return $this->id; } public function setDescription($description) { $this->description = $description; return $this; } public function getDescription() { return $this->description; } public function setPrice($price) { $this->price = $price; return $this; } public function getPrice() { return $this->price; } }
Video.php
namespace Entities; use Doctrine\ORM\Mapping as ORM; class Video extends Product //Important that Video extends Product { private $file_name; private $release_date; private $artist; public function setFileName($fileName) { $this->file_name = $fileName; return $this; } public function getFileName() { return $this->file_name; } public function setReleaseDate($releaseDate) { $this->release_date = $releaseDate; return $this; } public function getReleaseDate() { return $this->release_date; } public function setArtist(\Entities\Artist $artist = null) { $this->artist = $artist; return $this; } public function getArtist() { return $this->artist; } }
3) Create a new car and a new video
This is what goes into my CodeIgniter controller. The code assumes that you created an artist named Metallica and a brand named Ford.
public function createVideo() { //Instantiate new Entities\Video object $video = new Entities\Video; //Since it extends Entities\Product you can set the common Product properties $video->setDescription('This is a Metallica clip'); $video->setPrice(19.95); //Setting the custom Video properties $artist = $this->doctrine->em->getRepository('Entities\Artist')->findOneBy(array('name' => 'Metallica')); $video->setArtist($artist); $video->setReleaseDate(new DateTime()); $video->setFileName('metallica.mp4'); //Save $this->doctrine->em->persist($video); $this->doctrine->em->flush(); } public function createCar() { //Instantiate new Entities\Car object $car = new Entities\Car; //Since it extends Entities\Product you can set the common Product properties $car->setDescription('This is Ford Mondeo of 2011'); $car->setPrice(19.95); //Setting the custom Car properties $brand = $this->doctrine->em->getRepository('Entities\Brand')->findOneBy(array('name' => 'Ford')); $car->setBrand($brand); $car->setReleaseDate(DateTime::createFromFormat('Ym-d', '2011-11-15')); $car->setModel('Mondeo'); //Save $this->doctrine->em->persist($car); $this->doctrine->em->flush(); }
4) Extract all products
An example of extracting all products
public function extractAllProducts() { $products = $this->doctrine->em->getRepository('Entities\Product')->findAll(); foreach($products as $product) { printf('%s for € %s<br />', $product->getDescription(), $product->getPrice()); } }
This leads to
This is a Metallica clip for € 19.95 This is Ford Mondeo of 2011 for € 19.95
An example of how to extract all videos
public function extractAllVideos() { $videos = $this->doctrine->em->getRepository('Entities\Video')->findAll(); foreach($videos as $video) { printf('%s, released %s for € %s<br />', $video->getDescription(), $video->getReleaseDate()->format('Y'), $video->getPrice()); } }
This leads to
This is a Metallica clip, released 2012 for € 19.95