如何将枚举值保存到数据库中,使用带有 doctrine 和 symfony2 的自定义枚举数据类型


How to save enum value to the database, with custom enum data type with doctrine and symfony2?

这是我原始问题的后续问题:使用 symfony2 将 mysql 枚举迁移到教义实体的最佳策略?

我已经按照此处的说明成功添加了枚举数据类型:http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/cookbook/mysql-enums.html更具体地说,我使用后一部分使用了解决方案 2,其中我创建了一个基本的 EnumType 类,然后像这样扩展它:

<?php
namespace CP'AdminBundle'DataTypes;
class EnumContactBasicGender extends EnumType
{
    protected $name = 'EnumContactBasicGender';
    protected $values = array('m','f');
}

我的 EnumType 类看起来像:

<?php
namespace CP'AdminBundle'DataTypes;
use Doctrine'DBAL'Types'Type;
use Doctrine'DBAL'Platforms'AbstractPlatform;
abstract class EnumType extends Type
{
    protected $name;
    protected $values = array();
    public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        $values = array_map(function($val) { return "'".$val."'"; }, $this->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 enum value given: '".$this->value."' for enum: '".$this->name."'");
        }
        return $value;
    }
    public function getName()
    {
        return $this->name;
    }
}

然后我像这样注册了我的枚举:

<?php
namespace CP'AdminBundle;
use Doctrine'DBAL'Types'Type;
use Symfony'Component'HttpKernel'Bundle'Bundle;
class CPAdminBundle extends Bundle
{
 public function boot()
    {
        $em = $this->container->get('doctrine.orm.entity_manager');
        Type::addType('EnumContactBasicGender', 'CP'AdminBundle'DataTypes'EnumContactBasicGender');
        Type::addType('EnumContactBasicType', 'CP'AdminBundle'DataTypes'EnumContactBasicType');
        $em->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('EnumContactBasicGender','EnumContactBasicGender');
        $em->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('EnumContactBasicType','EnumContactBasicType');
    }
}

当我运行命令 ./app/console doctrine:generate:entities CP 时,它可以工作!它使用新的枚举数据类型创建我的实体,它毫无问题地创建 setter 和 getter,我的一个实体如下所示:

<?php
namespace CP'AdminBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Doctrine'Common'Collections'ArrayCollection;

/**
 * CP'AdminBundle'Entity'ContactBasic
 *
 * @ORM'Table(name="contacts_basics")
 * @ORM'Entity(repositoryClass="CP'AdminBundle'Entity'ContactBasicRepository")
 */
class ContactBasic
{
    /** Field #1 (contacts_id) **/
    /**
    * @var integer $contacts_id
    * @ORM'Column(type="integer",nullable=false)
    * @ORM'Id
    * @ORM'GeneratedValue(strategy="AUTO")
    */
    private $contacts_id;
    /** enum ('m','f') **/
    /**
    * @ORM'Column(type="EnumContactBasicGender",nullable=false)
    */
    private $gender;
    /** enum ('non-customer','customer','blacklisted') **/
    /**
    * @ORM'Column(type="EnumContactBasicType",nullable=false)
    */
    private $type;
        /** more omitted properties here **/
    /**
     * Set gender
     *
     * @param EnumContactBasicGender $gender
     */
    public function setGender('EnumContactBasicGender $gender)
    {
        $this->gender = $gender;
    }
    /**
     * Get gender
     *
     * @return EnumContactBasicGender 
     */
    public function getGender()
    {
        return $this->gender;
    }
    /**
     * Set type
     *
     * @param EnumContactBasicType $type
     */
    public function setType('EnumContactBasicType $type)
    {
        $this->type = $type;
    }
    /**
     * Get type
     *
     * @return EnumContactBasicType 
     */
    public function getType()
    {
        return $this->type;
    }
        /** more omitted setters and getters here **/
}
当我创建一个夹具加载

器时,我的问题出现了,我不知道如何设置任何枚举值以将它们保存到数据库中,到目前为止,我的夹具加载器类如下所示:

<?php
namespace CP'AdminBundle'DataFixtures'ORM;
use Doctrine'Common'DataFixtures'FixtureInterface;
use Doctrine'Common'Persistence'ObjectManager;
use CP'AdminBundle'Entity'ContactBasic;
use CP'AdminBundle'DataTypes'EnumContactBasicGender;
use CP'AdminBundle'DataTypes'EnumContactBasicType;

class ContactBasicLoader implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {

        $contact = new ContactBasic();
      //  $contact->setGender(new EnumContactBasicGender());
        $contact->setGender('m');
       // $contact->setType(new EnumContactBasicType());
        $contact->setType('customer');
        $manager->persist($contact);
        $manager->flush();


    }
}

当我运行./app/console doctrine:fixtures:load时,我收到以下错误:

Catchable Fatal Error: Argument 1 passed to CP'AdminBundle'Entity'ContactBasic::setGender() must be an instance of EnumContactBasicGender, string given

但是如果我像上面注释的行一样传递类,我也会出现错误。

有人可以解释一下我需要如何设置所需的值吗?

我遇到了一个非常相似的问题,我通过在 XXXEnumType 类中添加相同的值数组来解决,但公共和静态,这样我在一个地方指定了我的枚举的内容,从任何地方访问它并获取它:)

但首先,检查您是否在 app/config/config.yml 中添加了my_foo_type:

# Doctrine Configuration
doctrine:
    dbal:
        driver:   %database_driver%
        host:     %database_host%
        port:     %database_port%
        dbname:   %database_name%
        user:     %database_user%
        password: %database_password%
        charset:  UTF8
        types:
          my_foo_type:      use XXX'DBAL'XXXEnumType
        mapping_types:
          enum: string

<?php
namespace XXX'DBAL;
class XXXEnumType extends EnumType
{
    protected $name = 'enum_xxx';
    protected $values = array('first', 'second', 'last');
    public static $static_name = 'enum_xxx';
    public static $static_values = array('first', 'second', 'last');
    public function getValues()
    {
        return $this->values;
    }
}

从我项目的其他地方,我可以做:

use XXX'DBAL'XXXEnumType;

foreach (XXXEnumType::$static_values as $value)
{
    //do some stuff
}

希望对您有所帮助,

Linuxatico

Doctrine 没有完全支持枚举。枚举类型看起来很专业,但没有人以这种方式使用枚举。解决方法是使用整数值在实体中设置少量静态变量,并将枚举字段设置为整数类型。

对于您的问题,我将更改性别设置者:

  • 无方法参数 键入并传递一个简单的字符串
  • 从字符串构建一个枚举对象
  • 将枚举对象分配给实体。

问候麦克斯