0

I am wondering how to approach the use case that I need different types of an entity. In my case, I want to create an Approval-Entity. Yet there are different kinds of approvals I have to tell apart.

I am wondering if I should create a type field and then handle the different types via type constants that I also store in the database, e.g.:

use Doctrine\ORM\Mapping as ORM;

/**
 * Approval
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Hn\AssetDbBundle\Entity\ApprovalRepository")
 */
class Approval
{
    const SOME_TYPE = 1;
    const SOME_OTHER_TYPE = 2;

    /**
     * @var integer
     * @ORM\Column(name="type", type="integer")
     */

    private $type;
}

Another approach would be to make my Approval Entity abstract then extend SomeTypeApproval and SomeOtherTypeApproval from it. This seems like a more OOP solution to me but as the question should imply, I am somewhat unsure.

So I am wondering what the up- and downsides of each approach are in order to decide which route I should follow.

k0pernikus
  • 41,137
  • 49
  • 170
  • 286
  • In terms of how to inherit from entities, the [difference between Single Table Inheritance and Class Table Inheritance](http://stackoverflow.com/q/2946454/457268) seems to relevant – k0pernikus Jul 14 '14 at 13:09

2 Answers2

0

I would say that it's a bit overkill to create different Types of Entities for basically the same thing.

I had something similiar, i needed a way to tell a Entity which Type of Entity it is.

I just created another Entity "EntityType", where i stored all Types in the Database and just flaged the Entity with the id of the Type.

So your 2 Entities would be

use Doctrine\ORM\Mapping as ORM;

/**
 * Approval
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Hn\AssetDbBundle\Entity\ApprovalRepository")
 */
class Approval
{

    /**
     * @var integer
     * ManyToOne Relation to "ApprovalType"
     */

    private $type;
}

And the ApprovalType

/**
 * ApprovalType
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Hn\AssetDbBundle\Entity\ApprovalTypeRepository")
 */
class ApprovalType
{
    //Here you can define the type
    private $name;

    //OneToMany Relationship to the Approvals
    private $approvals;
}

Working perfectly for me and i think it suites the case pretty well and is the perfect mix of OOP and "keep it simple"

KhorneHoly
  • 4,245
  • 5
  • 41
  • 66
0

In order to differentiate the types, I followed up the object oriented path. I introduced a BaseApproval class which has all the shared fields:

<?php

namespace My\Bundle\\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ExecutionContextInterface;

/**
 * @ORM\Entity

 * @ORM\Table()
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({
 *      "someType" = "My\Bundle\Entity\Approvals\SomeTypeApproval",
 *      "someOtherType" = "My\Bundle\Entity\Approvals\SomeOtherTypeApproval",
 *      "yetAnotherType" = "My\Bundle\Entity\Approvals\YetAnotherTypeApproval"
 * })
 */

abstract class BaseApproval
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="textField", type="text", nullable=true)
     */
    private $textField;

    ...
}

The types are only some basic classes in my case, as there are no type specific fields:

<?php
namespace My\Bundle\Entity\Approvals;

use Doctrine\ORM\Mapping as ORM;
use My\Bundle\Entity\BaseApproval;

/**
 * @ORM\Entity
 */
class SomeTypeApproval extends BaseApproval
{
}

I went with single table inheritance as the different types share the same fields and it is unlikely that this will change much. Yet even if one type were to get additional fields, I could then define them in its entity class alone without polluting the other types. (On the database side, all types will have the same fields, those that aren't defined for all will be nulled).

I preferred this approach as I have the ability to typehint the approvals when I add them to an entity or could easily attach an listener to them without manually checking some field.

k0pernikus
  • 41,137
  • 49
  • 170
  • 286