2012-05-27 5 views
2

Это Followup вопрос от моего первоначального вопроса: Best strategy for migrating mysql enums to doctrine entities with symfony2?Как сохранить значение enum в базе данных, с пользовательским типом данных enum с доктриной и 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 доктрины: генерировать: объекты CP это работает! Он создает свои объекты с новыми типами перечисления данных, он создает сеттер и добытчик без проблем, одна из моих сущностей выглядят следующим образом:

<?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 Доктрина светильников: нагрузка я следующая ошибка:

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

но если я передаю класс, как прокомментированные строки выше, я также получаю сообщение об ошибке.

Может кто-нибудь объяснить, как мне нужно установить необходимые значения?

ответ

1

я столкнулся с очень подобным вопросом, я решил, добавив в классе XXXEnumType тот же массив значений, но общественных и статических, таким образом я указал в одном месте содержания из моего перечисления, доступ к нему из любого места и для него:

Но сначала проверьте, добавили ли вы my_foo_type в app/config/config.YML:

# 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

+1

Я думаю, что это помогает, я занимаюсь этим в течение 4 дней, я думаю, что то, что я собираюсь делать, что, вероятно, самый легкий, - это обрабатывать мои перечисления как строки, и как только я получу перекодировку моего унаследованного приложения эти поля вернутся к перечислению через mysql и просто забудьте об использовании командной строки symfony для обновления моей схемы базы данных, мне просто нужно это сделать самому! – MikeGA

+1

В способе, которым я опубликовал, перечисления обрабатываются как строки, а дополнительный элемент управления - если вы вставляете строку, отличную от указанной, она вызывает ошибку – linuxatico

1

Doctrine не имеет полной поддержки для перечислений. Типы перечислений выглядят PRO, но никто не играет с перечислениями таким образом. Обходной путь состоит в том, чтобы установить несколько статических vars в сущности с целочисленным значением и установить поле перечисления в целочисленный тип.

С вашим вопросом я изменю сеттер пола:

  • нет метода Типа параметра и пройти простую строку
  • из строки построить перечисление объективистских
  • присвоить enumObject к объекту.

С уважением, Max

Смежные вопросы