Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constants in Doctrine 2 entities

Suppose i'm having the following Doctrine 2 entity:

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 */
class User {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     *
     * @var int
     */
    protected $id;

    /**
     * @ORM\Column(length=100)
     *
     * @var string
     */
    protected $name;

    /**
     * @ORM\Column(type="integer")
     *
     * @var int
     */
    protected $status;
}

The User can have several statuses, for example: Pending, Active, Suspended. These statuses are needed throughout the code (services, repositories, etc.) and also in the UI layer (a User edit form would display them in a dropdown).

In order to avoid defining them in multiple places, what i've done so far was to use a class to hold them all (all the application's constants), and it looks somewhat like this:

class App_Constants extends Zrzr_Constants
{

    protected static $_constants = array( 
        'users' => array( 
            'status' => array( 
                0 => 'Pending', 
                1 => 'Active',
                2 => 'Suspended' ) ) );

}

The base class (Zrzr_Constants) would offer some methods to retrieve them, and it looks like this:

class Zrzr_Constants
{
    protected static $_constants = array();

    public static function getConstantValues( $key, $subkey )
    {
        // ...
    }

    public static function getConstantByName( $name )
    {
        // ...
    }
}

Common usage would be:

// example of retrieval by constant name ... it would return an integer
$pendingStatus = App_Constants::getConstantByName( 'USERS.STATUS.PENDING' );

// example of retrieval for UI display purposes ... would return an array
$statuses = App_Constants::getConstantValues('users', 'status');

Of course this means that there are some limitations in that the constant labels cannot contain dots, but i can live with it.

Using Doctrine 2 and going the DDD way however, tells me that the 'status' field should be in fact a 'value object' (but Doctrine 2 does not support value objects yet), or at least that i should have the constants defined within the entity (using const).

My question is how would i do this so that i avoid constant redefinition for the UI layer? I need to have access to the constant by name (in the code) and to have all the possible values for such a field in the case of a UI dropdown (for example).

like image 825
Ghola Avatar asked Aug 01 '11 12:08

Ghola


2 Answers

you can define your class as in the following example

class ContactResource
{
   const TYPE_PHONE = 1;
   const TYPE_EMAIL = 2;
   const TYPE_BIRTDAY = 3;
   const TYPE_ADDRESS = 4;
   const TYPE_OTHER = 5;
   const TYPE_SKYPE = 6;
   const TYPE_LINKEDIN = 7;
   const TYPE_MEETUP = 8;
   const TYPE_TELEGRAM = 9;
   const TYPE_INSTAGRAM = 10;
   const TYPE_TWITTER = 11;

   public static $resourceType = array(
       ContactResource::TYPE_PHONE => "Phone",
       ContactResource::TYPE_EMAIL => "Email",
       ContactResource::TYPE_BIRTDAY => "Birtday",
       ContactResource::TYPE_ADDRESS => "Address",
       ContactResource::TYPE_OTHER => "Other",
       ContactResource::TYPE_SKYPE => "Skype",
       ContactResource::TYPE_LINKEDIN => "LinkedIn",
       ContactResource::TYPE_MEETUP => "Meetup",
       ContactResource::TYPE_TELEGRAM => "Telegram",
       ContactResource::TYPE_INSTAGRAM => "Instagram",
       ContactResource::TYPE_TWITTER => "Twitter",
   );

   /**
   * @var integer
   *
   * @ORM\Column(type="integer", length=2)
   *
   */
   private $type;


   public function __toString()
   {
      return (string)$this->getType();
   }

   public function getType()
   {
      if (!is_null($this->type)) {
          return self::$resourceType[$this->type];
      } else {
          return null;
      }
   }

   public static function getTypeList() {
      return self::$resourceType;
   }

}

If you need to get the type in Twig

{{ entity.type }}

For the list of choices

ContactResource::getTypeList()

Hope works for you!

like image 126
xandrucancelas Avatar answered Oct 21 '22 12:10

xandrucancelas


I think, you can do it this way:

class User {
  const STATUS_PENDING = 'Pending';
  const STATUS_ACTIVE = 'Active';
  const STATUS_SUSPENDED = 'Suspended';

  public static function getStatusList() {
    return array(
                 self::STATUS_PENDING, 
                 self::STATUS_ACTIVE, 
                 self::STATUS_SUSPENDED
                );
  }

  public function getStatus() {...}

  public function setStatus($value) {...}

  public function isStatusPending() {...} //If you need it
}

On the UI layer, you can get text versions of your statuses using localization service (if status constants are numbers, UI layer can convert them to strings by adding prefix, for example user_status_0). In Symfony2 views you can use trans Twig filter for that to get text version of user status from user localization domain.

If your website is just in one language, then just User::STATUS_XXX will do fine, I think. I don't think you should overcomplicate the matter by creating a new class to hold statuses of the user.

If you will end up having many statuses or some other related things, I think you will have to create a separate entity for them.

like image 38
Vladislav Rastrusny Avatar answered Oct 21 '22 10:10

Vladislav Rastrusny