Jak ustawić wartość domyślną w Doctrine 2?
Jak ustawić wartość domyślną w Doctrine 2?
Odpowiedzi:
Domyślne wartości bazy danych nie są obsługiwane „przenośnie”. Jedynym sposobem użycia domyślnych wartości bazy danych jest użycie columnDefinition
atrybutu mapowania, w którym określa się SQL
fragment DEFAULT
kodu ( łącznie z przyczyną) dla kolumny, na którą mapowane jest pole.
Możesz użyć:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Preferowane są wartości domyślne na poziomie PHP, ponieważ są one również odpowiednio dostępne dla nowo utworzonych i utrwalonych obiektów (Doctrine nie wróci do bazy danych po utrwaleniu nowego obiektu w celu uzyskania wartości domyślnych).
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
Zauważ, że używa to SQL DEFAULT
, który nie jest obsługiwany w niektórych polach, takich jak BLOB
i TEXT
.
options={"default": 0}
Uważaj, aby używać „i nie”, ponieważ powoduje to błędy w mojej wersji doktryny.
Skonfiguruj konstruktor w swojej encji i ustaw tam domyślną wartość.
Posługiwać się:
options={"default":"foo bar"}
i nie:
options={"default"="foo bar"}
Na przykład:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Jeszcze jeden powód, dla którego przeczytaj dokumentację Symfony, która nigdy nie wyjdzie z mody. Istnieje proste rozwiązanie dla mojego konkretnego przypadku i polega na ustawieniu field type
opcji empty_data
na wartość domyślną.
Ponownie, to rozwiązanie jest tylko dla scenariusza, w którym puste dane wejściowe w formularzu ustawiają pole DB na null.
Żadna z poprzednich odpowiedzi nie pomogła mi w moim konkretnym scenariuszu, ale znalazłem rozwiązanie.
Miałem pole formularza, które musiało zachowywać się następująco:
Następnie wypróbowałem wszystkie podane tutaj zalecenia. Pozwól mi je wymienić:
<?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';
}
...
}
Nic z tego nie działało, a wszystko z powodu tego, jak Symfony używa twojej klasy Entity.
Pola formularza Symfony zastępują wartości domyślne ustawione dla klasy Entity.
Oznacza to, że w schemacie dla bazy danych może być zdefiniowana wartość domyślna, ale jeśli pozostawisz niepotrzebne pole puste podczas przesyłania formularza, form->handleRequest()
wnętrze form->isValid()
metody zastąpi te wartości domyślne w Entity
klasie i ustawi je na wartości pola wejściowego. Jeśli wartości pola wejściowego są puste, Entity
właściwość zostanie ustawiona na null
.
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
Ustawić wartość domyślną na kontrolerze po form->handleRequest()
wewnątrz form->isValid()
metody:
...
if ($myEntity->getMyColumn() === null) {
$myEntity->setMyColumn('myDefaultValue');
}
...
Nie jest to piękne rozwiązanie, ale działa. Prawdopodobnie mógłbym zrobić, validation group
ale mogą być ludzie, którzy postrzegają ten problem jako transformację danych, a nie sprawdzanie poprawności danych , pozostawiam to tobie do podjęcia decyzji.
Próbowałem również zastąpić Entity
seter w ten sposób:
...
/**
* Set myColumn
*
* @param string $myColumn
*
* @return myEntity
*/
public function setMyColumn($myColumn)
{
$this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;
return $this;
}
...
To, chociaż wygląda na czystsze, nie działa . Powodem jest to, że form->handleRequest()
metoda zła nie używa metod ustawiających Model do aktualizacji danych ( form->setData()
po więcej szczegółów).
Obejście Kiedyś było LifeCycleCallback
. Na przykład wciąż czekam, aby sprawdzić, czy istnieje jakaś „natywna” metoda @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()); }
Możesz to zrobić również za pomocą 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>
Oto jak sam to rozwiązałem. Poniżej znajduje się przykład jednostki z domyślną wartością dla MySQL. Wymaga to jednak również skonfigurowania konstruktora w jednostce i ustawienia wartości domyślnej.
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
idzie bezpośrednio ponownie w celu posiadania ORM, czyli abstrakcji z bazy danych. To rozwiązanie zakłóci przenośność, sprawi, że twoje oprogramowanie będzie zależne od dostawcy DB, a także złamie narzędzia Doctrine Migrations.
Działa dla mnie również w bazie danych mysql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Nic z tego nie działało dla mnie. Znalazłem trochę dokumentacji na stronie doktryny, która mówi, aby ustawić wartość bezpośrednio, aby ustawić wartość domyślną.
private $default = 0;
To wstawiło wartość, którą chciałem.
Dodanie do świetnej odpowiedzi na @romanb.
Dodaje to trochę narzutu przy migracji, ponieważ oczywiście nie można utworzyć pola bez ograniczenia zerowego i bez wartości domyślnej.
// 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");
Dzięki tej odpowiedzi zachęcam do zastanowienia się, dlaczego w ogóle potrzebujesz domyślnej wartości w bazie danych? I zwykle pozwala na tworzenie obiektów bez ograniczenia zerowego.
Jeśli używasz definicji yaml dla swojej encji, następujące działania działają na mnie w bazie danych postgresql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
używałeś przed spłukaniem? Doctrine wydaje się definiować wartość domyślną na zero. Jedynym rozwiązaniem w YAML jest określenie wartości domyślnej W klasie podmiot, który wydaje mi się głupie, ponieważ już zdefiniowane w YAML ... -_-
Walczyłem z tym samym problemem. Chciałem mieć domyślną wartość z bazy danych do encji (automatycznie). Zgadnij co, zrobiłem to :)
<?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";
Chociaż ustawienie wartości w konstruktorze działałoby, lepszym rozwiązaniem może być użycie zdarzeń cyklu życia Doctrine.
Wykorzystując prePersist
Zdarzenie cyklu życia, możesz ustawić wartość domyślną dla swojej jednostki tylko przy początkowym utrwaleniu.
hack
. Nigdy nie polegaj na hakach.
Zachowaj ostrożność podczas ustawiania wartości domyślnych w definicji właściwości! Zrób to w konstruktorze, aby zachować bezproblemowe działanie. Jeśli zdefiniujesz to w definicji właściwości, utrwal obiekt w bazie danych, a następnie wykonaj częściowe ładowanie, a następnie właściwości nie załadowane ponownie będą miały wartość domyślną. Jest to niebezpieczne, jeśli chcesz ponownie utrwalić obiekt.