From 04527a8bcb209217c12c0e2db0069af82f3fd3d2 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 31 Mar 2011 21:49:32 +0200 Subject: [PATCH] Add cookbook entry on MySQL Enums. --- en/cookbook/mysql-enums.rst | 189 ++++++++++++++++++++++++++++++++++++ en/index.rst | 3 +- 2 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 en/cookbook/mysql-enums.rst diff --git a/en/cookbook/mysql-enums.rst b/en/cookbook/mysql-enums.rst new file mode 100644 index 000000000..0e6e388df --- /dev/null +++ b/en/cookbook/mysql-enums.rst @@ -0,0 +1,189 @@ +Mysql Enums +=========== + +The type system of Doctrine 2 consists of flyweights, which means there is only +one instance of any given type. Additionally types do not contain state. Both +assumptions make it rather complicated to work with the Enum Type of MySQL that +is used quite a lot by developers. + +When using Enums with a non-tweaked Doctrine 2 application you will get +errors from the Schema-Tool commands due to the unknown database type "enum". +By default Doctrine does not map the MySQL enum type to a Doctrine type. +This is because Enums contain state (their allowed values) and Doctrine +types don't. + +This cookbook entry shows two possible solutions to work with MySQL enums. +But first a word of warning. The MySQL Enum type has considerable downsides: + +- Adding new values requires to rebuild the whole table, which can take hours + depending on the size. +- Enums are ordered in the way the values are specified, not in their "natural" order. +- Enums validation mechanism for allowed values is not necessarily good, + specifying invalid values leads to an empty enum for the default MySQL error + settings. You can easily replicate the "allow only some values" requirement + in your Doctrine entities. + +Solution 1: Mapping to Varchars +------------------------------- + +You can map ENUMs to varchars. You can register MySQL ENUMs to map to Doctrine +varchars. This way Doctrine always resolves ENUMs to Doctrine varchars. It +will even detect this match correctly when using SchemaTool update commands. + +.. code-block:: php + + getConnection(); + $conn->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'varchar'); + +In this case you have to ensure that each varchar field that is an enum in the +database only gets passed the allowed values. You can easily enforce this in your +entities: + +.. code-block:: php + + status = $status; + } + } + +If you want to actively create enums through the Doctrine Schema-Tool by using +the **columnDefinition** attribute. + +.. code-block:: php + + values); + + return "ENUM(".implode(", ", $values).") COMMENT '(DC2Type:".$this->name.")'"; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value; + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if (!in_array($value, $this->values)) { + throw new \InvalidArgumentException("Invalid '".$this->name."' value."); + } + return $value; + } + + public function getName() + { + return $this->name; + } + } + +With this base class you can define an enum as easily as: + +.. code-block:: php + +