【问题标题】:How to save enum value to the database, with custom enum data type with doctrine and symfony2?如何使用带有学说和 symfony2 的自定义枚举数据类型将枚举值保存到数据库?
【发布时间】:2012-06-02 07:56:07
【问题描述】:

这是我原始问题的后续问题: Best strategy for migrating mysql enums to doctrine entities with symfony2?

我已成功按照此处的说明添加枚举数据类型: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 dictionary: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 dictionary:fixtures:load 时,我收到以下错误:

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

但如果我像上面注释的行那样通过类,我也会收到错误。

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

【问题讨论】:

    标签: php symfony doctrine-orm


    【解决方案1】:

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

    但首先,请检查您是否在 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

    【讨论】:

    • 我认为它有帮助,我已经处理了 4 天,我想我要做什么,这可能是最简单的将我的枚举视为字符串,一旦我通过重新编码我的旧应用程序通过 mysql 将这些字段转换回枚举,然后忘记使用 symfony 命令行更新我的数据库模式,我只需要自己做!
    • 在我发布的方式中,枚举作为字符串处理,如果您插入与指定字符串不同的字符串,则会引发错误
    【解决方案2】:

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

    对于你的问题,我将更改性别设置器:

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

    问候, 最大

    【讨论】:

      猜你喜欢
      • 2018-04-22
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      相关资源
      最近更新 更多