Comment définir une valeur par défaut dans Doctrine 2?
Les valeurs par défaut de la base de données ne sont pas "supportables". La seule façon d'utiliser les valeurs par défaut de la base de données consiste à utiliser l'attribut de mappage columnDefinition
pour spécifier le fragment SQL
(DEFAULT
cause inclus) de la colonne à laquelle le champ est mappé.
Vous pouvez utiliser:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Les valeurs par défaut de niveau PHP sont préférables car elles sont également correctement disponibles sur les objets nouvellement créés et persistants (Doctrine ne reviendra pas dans la base de données après la persistance d'un nouvel objet pour obtenir les valeurs par défaut).
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
Notez que cela utilise SQL DEFAULT
, qui n'est pas pris en charge pour certains champs comme BLOB
et TEXT
.
Configurez un constructeur dans votre entité et définissez-y la valeur par défaut.
Utilisation:
options={"default":"foo bar"}
et pas:
options={"default"="foo bar"}
Par exemple:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Une raison de plus pour laquelle lire la documentation de Symfony ne sera jamais hors de tendance. Il existe une solution simple pour mon cas spécifique et consiste à définir l'option field type
empty_data
sur une valeur par défaut.
Là encore, cette solution concerne uniquement le scénario dans lequel une entrée vide dans un formulaire définit le champ de base de données sur null.
Aucune des réponses précédentes ne m'a aidé avec mon scénario spécifique mais j'ai trouvé une solution.
J'avais un champ de formulaire qui devait se comporter comme suit:
J'ai ensuite essayé toutes les recommandations données ici. Laissez moi les lister:
<?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';
}
...
}
Les champs de formulaire Symfony remplacent les valeurs par défaut définies dans la classe Entity. Cela signifie que votre schéma pour votre base de données peut avoir une valeur par défaut définie, mais si vous laissez un champ non obligatoire vide lors de la soumission de votre formulaire, le form->handleRequest()
de votre méthode form->isValid()
remplacera les valeurs par défaut de votre classe Entity
et sera défini. les aux valeurs du champ d'entrée. Si les valeurs du champ d'entrée sont vides, la propriété Entity
sera définie sur null
.
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
Définissez la valeur par défaut sur votre contrôleur après form->handleRequest()
dans votre méthode form->isValid()
:
...
if ($myEntity->getMyColumn() === null) {
$myEntity->setMyColumn('myDefaultValue');
}
...
Pas une belle solution mais ça marche. Je pourrais probablement créer un validation group
, mais il se peut que certaines personnes considèrent ce problème comme une transformation data plutôt que comme une validation data. Je vous laisse le soin de décider.
J'ai aussi essayé de remplacer le setter Entity
de cette façon:
...
/**
* Set myColumn
*
* @param string $myColumn
*
* @return myEntity
*/
public function setMyColumn($myColumn)
{
$this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;
return $this;
}
...
Ceci, même si cela a l'air plus propre, ça ne marche pas. La raison en est que la méthode evil form->handleRequest()
n'utilise pas les méthodes de définition du modèle pour mettre à jour les données (Dig into form->setData()
pour plus de détails).
La solution de contournement que j'ai utilisée était une LifeCycleCallback
. J'attends toujours de voir s'il existe une méthode "native", par exemple @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');
}
Vous pouvez aussi le faire en utilisant 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>
Voici comment je l'ai résolu pour moi-même. Vous trouverez ci-dessous un exemple d'entité avec une valeur par défaut pour MySQL. Cependant, cela nécessite également la configuration d'un constructeur dans votre entité et la définition de la valeur par défaut à cet endroit.
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'
Fonctionne pour moi sur une base de données mysql également:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Rien de tout cela n'a fonctionné pour moi. J'ai trouvé une documentation sur le site de la doctrine qui dit de définir directement la valeur pour définir une valeur par défaut.
http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/faq.html
private $default = 0;
Cela a inséré la valeur que je voulais.
Si vous utilisez la définition de yaml pour votre entité, les éléments suivants fonctionnent pour moi sur une base de données postgresql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
Ajout à la réponse brillante de @romanb.
Cela ajoute un peu de surcharge dans la migration, car vous ne pouvez évidemment pas créer de champ avec une contrainte non nulle et sans valeur par défaut.
// 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");
Avec cette réponse, je vous encourage à penser pourquoi vous avez besoin de la valeur par défaut dans la base de données en premier lieu? Et généralement, cela permet de créer des objets avec une contrainte non nulle.
Bien que définir la valeur dans le constructeur fonctionne, l’utilisation des événements Doctrine Lifecycle peut constituer une meilleure solution.
En exploitant l'événement prePersist
Lifecycle, vous pouvez définir votre valeur par défaut sur votre entité uniquement lors de la persistance initiale.
J'ai lutté avec le même problème. Je voulais avoir la valeur par défaut de la base de données dans les entités (automatiquement). Devinez quoi, je l'ai fait :)
<?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";
Soyez prudent lorsque vous définissez des valeurs par défaut pour la définition de la propriété! Faites-le dans le constructeur à la place, pour le garder sans problèmes. Si vous le définissez dans la définition de la propriété, conservez l'objet dans la base de données, effectuez un chargement partiel. Les propriétés non chargées auront à nouveau la valeur par défaut. Cela est dangereux si vous souhaitez conserver l'objet à nouveau.