Значение по умолчанию в Доктрине

Как установить значение по умолчанию в Doctrine 2?

Ответ 1

Значения по умолчанию для базы данных не поддерживаются "по-порту". Единственный способ использовать значения по умолчанию для базы данных - через атрибут columnDefinition mapping, где вы указываете фрагмент SQL (DEFAULT причина включительно) для столбца, на которое отображается поле.

Вы можете использовать:

<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}

Предпочтительны значения по умолчанию на уровне PHP, так как они также правильно доступны для вновь созданных и сохраняемых объектов (Doctrine не вернется к базе данных после сохранения нового объекта, чтобы получить значения по умолчанию).

Ответ 2

@ORM\Column(name="foo", type="decimal", precision=7, scale=2, options={"default" : 0})

Обратите внимание, что это использует SQL DEFAULT, который не поддерживается для некоторых полей, таких как BLOB и TEXT.

Ответ 3

Настройте конструктор в своей сущности и установите для него значение по умолчанию.

Ответ 4

Использование:

options={"default":"foo bar"}

и не:

options={"default"="foo bar"}

Например:

/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo

Ответ 5

Update

Еще одна причина, по которой прочитать документацию для Symfony никогда не исчезнет из тенденции. Для моего конкретного случая есть простое решение и установить значение field type empty_data в значение по умолчанию.

Опять же, это решение предназначено только для сценария, когда пустой ввод в форме устанавливает для поля БД значение null.

Фон

Ни один из предыдущих ответов не помог мне с моим конкретным сценарием, но я нашел решение.

У меня было поле формы, которое должно было вести себя следующим образом:

  • Не требуется, может быть оставлено пустым. (Используется "required" = > false)
  • Если оставить пустым, оно должно быть по умолчанию задано. Для лучшего пользовательского опыта я не задал значение по умолчанию в поле ввода, а скорее использовал атрибут html "placeholder", поскольку он менее навязчив.

Затем я попробовал все рекомендации, приведенные здесь. Позвольте мне перечислить их:

  • Задайте значение по умолчанию для свойства объекта:
<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}
  • Используйте аннотацию параметров:
@ORM\Column(name="foo", options={"default":"foo bar"})
  • Задайте значение по умолчанию для конструктора:
/**
 * @Entity
 */
class myEntity {
    ...
    public function __construct()
    {
        $this->myColumn = 'myDefaultValue';
    }
    ...
}
Ничего из этого не было, и все из-за того, как Symfony использует ваш класс Entity.

ВАЖНО

Поля формы Symfony переопределяют значения по умолчанию, установленные в классе Entity. Смысл, ваша схема для вашей БД может иметь значение по умолчанию, но если вы оставите необязательное поле пустым при отправке формы, form->handleRequest() внутри вашего метода form->isValid() переопределит эти значения по умолчанию в вашем классе Entity и установите их в значения полей ввода. Если значения поля ввода пустые, то для свойства Entity будет установлено значение null.

http://symfony.com/doc/current/book/forms.html#handling-form-submissions

Мое обходное решение

Задайте значение по умолчанию на вашем контроллере после form->handleRequest() внутри вашего метода form->isValid():

...
if ($myEntity->getMyColumn() === null) {
    $myEntity->setMyColumn('myDefaultValue');
}
...

Не красивое решение, но оно работает. Возможно, я мог бы сделать validation group, но могут быть люди, которые рассматривают эту проблему как преобразование данных, а не проверку данных, я оставляю это вам решать.


Сменить сеттер (не работает)

Я также попытался переопределить установщик Entity следующим образом:

...
/**
 * Set myColumn
 *
 * @param string $myColumn
 *
 * @return myEntity
 */
public function setMyColumn($myColumn)
{
    $this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;

    return $this;
}
...

Это, даже если оно выглядит более чистым, не работает. Причина заключается в том, что метод зла form->handleRequest() не использует методы настройки модели для обновления данных (для более подробной информации смотрите form->setData()).

Ответ 6

Обходной путь, который я использовал, был LifeCycleCallback. Все еще жду, чтобы увидеть, есть ли более "родной" метод, например @Column(type="string", default="hello default value").

/**
 * @Entity @Table(name="posts") @HasLifeCycleCallbacks
 */
class Post implements Node, \Zend_Acl_Resource_Interface {

...

/**
 * @PrePersist
 */
function onPrePersist() {
    // set default date
    $this->dtPosted = date('Y-m-d H:m:s');
}

Ответ 7

Вы можете сделать это, используя xml:

<field name="acmeOne" type="string" column="acmeOne" length="36">
    <options>
        <option name="comment">Your SQL field comment goes here.</option>
        <option name="default">Default Value</option>
    </options>
</field>

Ответ 8

Вот как я решил это для себя. Ниже приведен пример Entity со значением по умолчанию для MySQL. Однако это также требует установки конструктора в вашей сущности и для установки там значения по умолчанию.

Entity\Example:
  type: entity
  table: example
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
    label:
      type: string
      columnDefinition: varchar(255) NOT NULL DEFAULT 'default_value' COMMENT 'This is column comment'

Ответ 9

Работает для меня и в базе данных mysql:

Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: integer
            nullable: true
            options:
                default: 1

Ответ 10

Ничего из этого не сработало для меня. Я нашел некоторую документацию на сайте доктрины, которая говорит, чтобы установить значение непосредственно для установки значения по умолчанию.

http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/faq.html

private $default = 0;

Вставил нужное значение.

Ответ 11

Добавление к @romanb блестящего ответа.

Это добавляет небольшие затраты на перенос, потому что вы, очевидно, не можете создать поле с неопределенным ограничением и без значения по умолчанию.

// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "postgresql");

//lets add property without not null contraint        
$this->addSql("ALTER TABLE tablename ADD property BOOLEAN");

//get the default value for property       
$object = new Object();
$defaultValue = $menuItem->getProperty() ? "true":"false";

$this->addSql("UPDATE tablename SET property = {$defaultValue}");

//not you can add constraint
$this->addSql("ALTER TABLE tablename ALTER property SET NOT NULL");

С помощью этого ответа я рекомендую вам подумать, почему вам нужно значение по умолчанию в базе данных в первую очередь? И обычно это позволяет создавать объекты с ненулевым ограничением.

Ответ 12

Если вы используете определение yaml для своей сущности, следующее работает для меня в базе данных postgresql:

Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: boolean
            nullable: false
            options:
                default: false

Ответ 13

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

<?php
/**
 * Created by JetBrains PhpStorm.
 * User: Steffen
 * Date: 27-6-13
 * Time: 15:36
 * To change this template use File | Settings | File Templates.
 */

require_once 'bootstrap.php';

$em->getConfiguration()->setMetadataDriverImpl(
    new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
        $em->getConnection()->getSchemaManager()
    )
);

$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($em->getConnection()->getSchemaManager());
$driver->setNamespace('Models\\');

$em->getConfiguration()->setMetadataDriverImpl($driver);

$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();

// Little hack to have default values for your entities...
foreach ($metadata as $k => $t)
{
    foreach ($t->getFieldNames() as $fieldName)
    {
        $correctFieldName = \Doctrine\Common\Util\Inflector::tableize($fieldName);

        $columns = $tan = $em->getConnection()->getSchemaManager()->listTableColumns($t->getTableName());
        foreach ($columns as $column)
        {
            if ($column->getName() == $correctFieldName)
            {
                // We skip DateTime, because this needs to be a DateTime object.
                if ($column->getType() != 'DateTime')
                {
                    $metadata[$k]->fieldMappings[$fieldName]['default'] = $column->getDefault();
                }
                break;
            }
        }
    }
}

// GENERATE PHP ENTITIES!
$entityGenerator = new \Doctrine\ORM\Tools\EntityGenerator();
$entityGenerator->setGenerateAnnotations(true);
$entityGenerator->setGenerateStubMethods(true);
$entityGenerator->setRegenerateEntityIfExists(true);
$entityGenerator->setUpdateEntityIfExists(false);
$entityGenerator->generate($metadata, __DIR__);

echo "Entities created";

Ответ 14

При установке значения в конструкторе будет работать, использование событий жизненного цикла Doctrine может быть лучшим решением.

Используя событие prePersist Lifecycle Event, вы можете установить значение по умолчанию для своей сущности только при первоначальном сохранении.

Ответ 15

Будьте внимательны при настройке значений по умолчанию для определения свойств! Вместо этого сделайте это в конструкторе, чтобы сохранить его без проблем. Если вы определяете его по определению свойства, то сохраняйте объект в базе данных, затем выполняйте частичную загрузку, а затем не загруженные свойства снова будут иметь значение по умолчанию. Это опасно, если вы хотите снова сохранить объект.