Як встановити значення за замовчуванням у Doctrine 2?
Як встановити значення за замовчуванням у Doctrine 2?
Відповіді:
Значення за замовчуванням бази даних не підтримуються "портативно". Єдиний спосіб використання значень за замовчуванням бази даних - це columnDefinitionатрибут mapping, де ви вказуєте SQLфрагмент ( DEFAULTпричину включно) для стовпчика, у який відображено поле.
Ви можете використовувати:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Значення за замовчуванням на рівні PHP є кращими, оскільки вони також належним чином доступні для новостворених та збережених об'єктів (Доктрина не повернеться до бази даних після збереження нового об’єкта для отримання значень за замовчуванням).
<?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значення за замовчуванням.
Знову ж таки, це рішення є лише для сценарію, коли порожнє введення у формі встановлює нульове поле БД.
Жодна з попередніх відповідей не допомогла мені в конкретному сценарії, але я знайшов рішення.
У мене було поле форми, яке потрібно було поводити так:
Потім я спробував усі рекомендації, наведені тут. Дозвольте мені перерахувати їх:
<?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, яка є абстрагуванням від бази даних. Це рішення порушить портативність, забезпечить залежність вашого програмного забезпечення від постачальника даних DB, а також порушить інструменти міграції доктрин.
Для мене працює і база даних 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()перед промиванням? Здається, доктрина визначає значення за замовчуванням у null. Єдине рішення в yaml - це визначити значення за замовчуванням IN -класу сутності, яке здається мені німим, оскільки воно вже визначене в 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";
Хоча встановлення значення в конструкторі спрацює, кращим рішенням може бути використання подій життєвого циклу доктрини.
Використовуючи prePersistподію життєвого циклу, ви можете встановити значення за замовчуванням для вашої сутності лише на первісному збереженні.
hack. Ніколи не покладайтеся на хаків.
Будьте уважні, встановлюючи значення за замовчуванням для визначення властивості! Зробіть це замість цього в конструкторі, щоб зберегти його без проблем. Якщо ви визначите його за визначенням властивості, то збережіть об'єкт у базі даних, потім зробіть часткове завантаження, тоді не завантажені властивості знову матимуть значення за замовчуванням. Це небезпечно, якщо ви хочете знову зберегти об'єкт.