Skip to content

Instantly share code, notes, and snippets.

@geerteltink
Last active August 29, 2015 14:26
Show Gist options
  • Select an option

  • Save geerteltink/84159f006616b4029623 to your computer and use it in GitHub Desktop.

Select an option

Save geerteltink/84159f006616b4029623 to your computer and use it in GitHub Desktop.
Doctrine embedded value objects with single table inheritance
<?php
namespace ContentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use DateTime;
use DateTimeZone;
/**
* @ORM\Entity
* @ORM\Table(name="content")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({
* "default"="Content",
* "page"="PageContent",
* "post"="PostContent"
* })
*/
class Content
{
/**
* @var integer
*
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var Guid
*
* @ORM\Embedded(class="Guid")
*/
private $guid;
/**
* @var string
*
* @ORM\Column(type="text")
*/
private $title;
/**
* @var string
*
* @ORM\Column(type="text")
*/
private $body;
/**
* @var PublishStatus
*
* @ORM\Embedded(class="PublishStatus")
*/
private $status;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime")
*/
private $created;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime")
*/
private $modified;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime")
*/
private $published;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime")
*/
private $embargoed;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime")
*/
private $expires;
public function __construct(
$title,
$body
) {
$this->title = $title;
$this->body = $body;
$this->status = PublishStatus::draft();
$this->created = new DateTime('now', new DateTimeZone('UTC'));
}
public function publish(DateTime $published = null)
{
if (!$published) {
$published = new DateTime('now', new DateTimeZone('UTC'));
}
$this->status = PublishStatus::usable();
$this->published = clone $published;
}
public function withGuid(Guid $guid)
{
$this->guid = $guid;
}
public function withEmbargo(DateTime $embargoed = null)
{
$this->embargoed = clone $embargoed;
}
public function withExpiration(DateTime $expires = null)
{
$this->expires = clone $expires;
}
}
<?php
namespace ContentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Embeddable
*/
class Guid
{
/**
* @ORM\Column(type="string", nullable=true)
*/
protected $value;
public function __construct($value)
{
$this->value = \strval($value);
}
/**
* @return string
*/
public function __toString()
{
return $this->value;
}
}
<?php
namespace ContentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class PageContent extends Content
{
public function __construct(
$title,
$body
) {
parent::__construct($title, $body);
}
}
<?php
namespace ContentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class PostContent extends Content
{
/**
* @var string
*
* @ORM\Column(type="text")
*/
private $excerpt;
public function __construct(
$title,
$body,
$excerpt = null
) {
parent::__construct($title, $body);
$this->excerpt = $excerpt;
}
}
<?php
namespace ContentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Embeddable
*/
class PublishStatus
{
const STATE_DRAFT = 'draft';
const STATE_USABLE = 'usable';
const STATE_WITHHELD = 'withheld';
const STATE_CANCELED = 'canceled';
/**
* @ORM\Column(type="string")
*/
private $status;
/**
* @param string $status
* @throws \Exception
*/
public function __construct($status)
{
if (!in_array($status, [self::STATE_DRAFT, self::STATE_USABLE, self::STATE_WITHHELD, self::STATE_CANCELED])) {
throw new \Exception(sprintf('Invalid status: %s', $status));
}
$this->status = $status;
}
public static function draft()
{
return new self(self::STATE_DRAFT);
}
public static function usable()
{
return new self(self::STATE_USABLE);
}
public static function withheld()
{
return new self(self::STATE_WITHHELD);
}
public static function canceled()
{
return new self(self::STATE_CANCELED);
}
public function equals(PublishStatus $status)
{
return ($this->status == (string) $status);
}
/**
* @return string
*/
public function __toString()
{
return $this->status;
}
}
@geerteltink
Copy link
Copy Markdown
Author

When updating the schema I get this:

> php app/console doctrine:schema:update --force

[ReflectionException]
Property ContentBundle\Entity\PageContent::$guid does not exist

Without the single table inheritance it works perfectly and it creates the correct table structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment