SUBSCRIBE VIA RSS


Subscribe to our feed

Symfony Experts

Symfony Experts
If you have an urgent question for a symfony-related issue, this is the place to ask.

Topics

Stack Overflow


The old fashioned way

RECENT TUNES

March 14, 2009 – 2:46pm Symfony Propel Enum types

Propel does not support enum column types in its schemas, since the enum type is not support across all database types. There are a few ways around this.

1) Use another table to list the enum options. Pros: most flexible. Works nicely within symfony. Cons: means more joins in your queries.

2) Use enum anyway. You can add custom column types using a little known trick in your schema:

status:
  id:
  name: { type: varchar, sqltype:enum, size: "'inactive','active'", default: inactive }

Pros: You get your enum. Cons: Not very portable, a bit of a hack.

3) Simulate an enum column using your model. I typically end up doing this for columns that have a finite number of defined options *that will not change*. Pros: Fast. Cons: Not as flexible as optino 1. Example:


class UserProfilePeer extends BaseUserProfilePeer
{
  static protected $USER_TYPE_INTEGERS = array('student', 'supervisor', 'coordinator', 'researcher', 'admin');
  static protected $USER_TYPE_VALUES = null;

  /**
   * Returns a user type label from an index value.
   *
   * @param integer $index
   * @return string user type label
   * @author Scott Meves
   */
  static public function getUserTypeFromIndex($index)
  {
    return self::$USER_TYPE_INTEGERS[$index];
  }

  /**
   * Returns the user type index from a string value
   *
   * @param string $value 
   * @return integer $index
   * @author Scott Meves
   */
  static public function getUserTypeFromValue($value)
  {
    if (!self::$USER_TYPE_VALUES)
    {
      self::$USER_TYPE_VALUES = array_flip(self::$USER_TYPE_INTEGERS);
    }

    $values = strtolower($value);

    if (!isset(self::$USER_TYPE_VALUES[$value]))
    {
      throw new PropelException(sprintf('User type cannot take "%s" as a value', $value));
    }

    return self::$USER_TYPE_VALUES[strtolower($value)];
  }
  
  public static function getUserTypeOptions()
  { 
    return self::$USER_TYPE_INTEGERS;
  }
}
Posted by in  Uncategorized   |  

4 Responses to Symfony Propel Enum types

  1. Scott, curious why you wouldn’t use constants? You write you pull the last trick for “a finite number of defined options *that will not change*.”

    But then you put them in an array:

    static protected $USER_TYPE_INTEGERS = array(‘student’, ‘supervisor’, ‘coordinator’, ‘researcher’, ‘admin’);

    I like how fast and flexible this is. But wouldn’t constants better suggest that the intent was a fixed, unchanging, limited set? PHP arrays seem very flexible to me, even if you do apply the “protected” keyword. Seems like the only time I’d want to imitate an ENUM is when I wanted something that was not flexible.

  2. Scott Meves says:

    @lawrence, I don’t use constants in this case because I wanted to have my user types stored in an array, and php doesn’t support “constant” arrays.

  3. Jorge Chávez says:

    It’s too bad that not all DB support enum data types, but it’s nice to have at least some options to implement this.
    A few weeks ago I was trying to use enum, but at the end I decided to go for the adding table option.
    Perhaps the best possible solution yet is to simulate it like in this post.

  4. ksn135 says:
    class Section extends BaseSection
    {
      const TYPE_LIST      = 'list'
           ,TYPE_LINK      = 'link'
           ,TYPE_PAGE      = 'page'
           ,TYPE_VOTE      = 'vote'
           ,TYPE_AUTHORS   = 'authors'
     
    // add new above this line
            ;
      static public function getValidTypesAsArray($context = null)
      {
        $results = array();
        $ext = new ReflectionClass('Section');
        $constants = $ext->getConstants();
        foreach($constants as $name => $value)
        {
          if (!strncmp($name,'TYPE_',5))
          {
            // i18n translation
            $results[$value] = myTools::__($value);
          }
        }
        if($context)
        {
          $event = new sfEvent($this, 'section.update_valid_types');
          $context->dispatcher->filter($event, $results);
          $results = $event->getReturnValue();
        }
     
        return $results;
      }
    }