@antonowano
Профессиональный самоучка

Как настроить принимаемые значения некоторых полей в сущности?

Пример в сущности есть поле type, оно может принимать одно из значений: продам, куплю, сдам, сниму.
Как их заменить соответствующими ключами при этом не создавая отдельную таблицу для немногочисленных типов.
А при запросе получать конкретную значение, а не ключ.
Для этого нужно использовать конфигурационный файл?
  • Вопрос задан
  • 214 просмотров
Решения вопроса 1
lexxpavlov
@lexxpavlov
Программист, преподаватель
Можно использовать тип данных enum в записи. Enum для этого и предназначен. В базе будет использоваться число, а при получении данных из базы будет строка.
Вот стандартное решение в доке доктрины.
Если enum только один, то можно так и сделать. Но часто enum-ов много, и тогда я делаю вот такой способ:

Базовый класс:
<?php
namespace AppBundle\DBAL;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

abstract class EnumType extends Type
{
    protected $name;

    public static $VALUES = array();

    public static function getValues()
    {
        $values = array();
        foreach (static::$VALUES as $value) $values[$value] = $value;
        return $values;
    }

    public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        $values = array();
        foreach (static::$VALUES as $value) $values[] = "'$value'";
        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, static::$VALUES)) {
            throw new \InvalidArgumentException("Invalid value '$value' for enum '$this->name'.");
        }
        return $value;
    }

    public function getName()
    {
        return $this->name;
    }
}

И теперь легко сделать нужный enum:
<?php
namespace AppBundle\DBAL;

class MyType extends EnumType
{
    protected $name = 'mytype';

    const FIRST = 'first';
    const SECOND  = 'second';

    public static $VALUES = array(self::FIRST, self::SECOND);
}


Ну и в настройке указать тип:
doctrine:
    dbal:
        driver:   "%database_driver%"
        host:     "%database_host%"
        port:     "%database_port%"
        dbname:   "%database_name%"
        user:     "%database_user%"
        password: "%database_password%"
        charset:  UTF8
        types:
            mytype: AppBundle\DBAL\MyType
        mapping_types:
            enum: string


Теперь можно указать его в сущности:
class MyEntity
{
    /**
     * @var integer $id
     *
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    
   // ....
    
    /**
     * @var string
     *
     * @ORM\Column(type="mytype")
     */
    protected $type;


Для чего делать отдельный класс для каждого enum-а? Для типизации значений. Например, можно было взять список значений: $types = MyType::getValues(), или проверить тип: if ($val->getType() == MyType::FIRST) {}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы