Как установить значение по умолчанию в Doctrine 2?
Как установить значение по умолчанию в Doctrine 2?
Ответы:
Значения по умолчанию для базы данных не поддерживаются. Единственный способ использовать значения по умолчанию для базы данных - использовать columnDefinition
атрибут сопоставления, в котором вы указываете SQL
фрагмент ( DEFAULT
включающий причину) для столбца, в который отображается поле.
Ты можешь использовать:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Значения по умолчанию на уровне PHP предпочтительнее, поскольку они также правильно доступны для вновь создаваемых и сохраняемых объектов (Doctrine не вернется в базу данных после сохранения нового объекта для получения значений по умолчанию).
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
Обратите внимание, что здесь используется SQL DEFAULT
, который не поддерживается для некоторых полей, таких как BLOB
и TEXT
.
options={"default": 0}
будьте осторожны, используя «а не», так как это вызывает ошибки в моей версии доктрины.
Установите конструктор в вашей сущности и установите там значение по умолчанию.
Использование:
options={"default":"foo bar"}
и нет:
options={"default"="foo bar"}
Например:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Еще одна причина, почему чтение документации для Symfony никогда не выйдет из моды. Существует простое решение для моего конкретного случая и установить field type
параметр empty_data
в значение по умолчанию.
Опять же, это решение предназначено только для сценария, в котором пустой ввод в форме устанавливает для поля БД значение null.
Ни один из предыдущих ответов не помог мне с моим конкретным сценарием, но я нашел решение.
У меня было поле формы, которое должно было вести себя следующим образом:
Затем я попробовал все рекомендации, приведенные здесь. Позвольте мне перечислить их:
<?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()
более подробно).
Обходной путь, который я использовал, был 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');
}
if (!$this->getDtPosted()) { $this->setDtPosted(new \DateTime()); }
Вы можете сделать это, используя 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>
Вот как я решил это для себя. Ниже приведен пример 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'
columnDefinition
идет прямо против цели наличия ORM, который является абстракцией от базы данных. Это решение нарушит мобильность, сохранит зависимость вашего программного обеспечения от поставщика БД, а также сломает инструменты Doctrine Migrations.
У меня работает и в базе данных mysql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Ничто из этого не сработало для меня. Я нашел некоторую документацию на сайте доктрины, в которой говорится, чтобы установить значение напрямую, чтобы установить значение по умолчанию.
private $default = 0;
Это вставило значение, которое я хотел.
Добавление в @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");
С этим ответом я призываю вас задуматься, зачем вам сначала значение по умолчанию в базе данных? И обычно это позволяет создавать объекты с ненулевым ограничением.
Если вы используете определение yaml для своей сущности, для меня работает следующее в базе данных postgresql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
перед промывкой? Doctrine, похоже, определяет значение по умолчанию в null. Единственное решение в yaml - определить значение по умолчанию В классе сущностей, которое мне кажется глупым, поскольку оно уже определено в yaml ... -_-
Я боролся с той же проблемой. Я хотел получить значение по умолчанию из базы данных в сущности (автоматически). Угадай что, я сделал это :)
<?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";
Хотя установка значения в конструкторе будет работать, лучше использовать события жизненного цикла Doctrine.
Используя prePersist
событие жизненного цикла, вы можете установить значение по умолчанию для вашей сущности только при первоначальном сохранении.
hack
. Никогда не полагайтесь на хаки.
Будьте осторожны при установке значений по умолчанию при определении свойства! Вместо этого сделайте это в конструкторе, чтобы сохранить его без проблем. Если вы определите его в определении свойства, затем сохраните объект в базе данных, затем выполните частичную загрузку, тогда незагруженные свойства снова будут иметь значение по умолчанию. Это опасно, если вы хотите сохранить объект снова.