Valeur par défaut dans Doctrine
Comment définir une valeur par défaut dans Doctrine 2?
15 réponses
Les valeurs par défaut de la base de données ne sont pas prises en charge" de manière portative". La seule façon d'utiliser les valeurs par défaut de la base de données est via l'attribut de mappage columnDefinition
où vous spécifiez l'extrait de code SQL
(DEFAULT
cause inclusive) pour 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érées car elles sont également correctement disponibles sur les objets nouvellement créés et persistants (Doctrine ne reviendra pas à la base de données après avoir persisté un nouvel objet pour obtenir la valeur par défaut valeur).
<?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 la valeur par défaut.
Utilisation:
options={"default":"foo bar"}
Et non:
options={"default"="foo bar"}
Par exemple:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Mettre à jour
Une raison de plus pour laquelle lire la documentation pour Symfony ne sortira jamais de la tendance. Il existe une solution simple pour mon cas spécifique et consiste à définir l'option field type
empty_data
à une valeur par défaut.
Encore une fois, cette solution est uniquement pour le scénario où une entrée vide dans un formulaire définit le champ DB à null.
Contexte
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 formulaire champ qui devait se comporter comme suit:
- Non requis, peut être laissé en blanc. (Utilisé 'required' = > false)
- si elle est laissée vide, elle doit être définie par défaut sur une valeur donnée. Pour une meilleure expérience utilisateur, je n'ai pas défini la valeur par défaut sur le champ de saisie mais j'ai plutôt utilisé l'attribut html 'placeholder' car il est moins intrusif.
J'ai ensuite essayé toutes les recommandations données ici. Laissez-moi les énumérer:
- définit une valeur par défaut pour l'entité propriété:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
- utilisez les options annotation:
@ORM\Column(name="foo", options={"default":"foo bar"})
- définit la valeur par défaut du constructeur:
/**
* @Entity
*/
class myEntity {
...
public function __construct()
{
$this->myColumn = 'myDefaultValue';
}
...
}
Rien n'a fonctionné et tout cela à cause de la façon dont Symfony utilise votre classe d'Entité.
IMPORTANT
Les champs de formulaire Symfony remplacent les valeurs par défaut définies sur 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 requis vide lors de la soumission de votre formulaire, le form->handleRequest()
à l'intérieur de votre méthode form->isValid()
remplacera ces valeurs par défaut sur votre classe Entity
et les définira sur les valeurs du champ de saisie. Si les valeurs du champ de saisie sont vides, la propriété Entity
sera définie sur null
.
Http://symfony.com/doc/current/book/forms.html#handling-form-submissions
Ma Solution De Contournement
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 faites un validation group
mais il peut y avoir des gens qui voient ce problème comme une transformation de données plutôt quevalidation de données , je vous laisse décider.
Override Setter (Ne Fonctionne Pas)
J'ai également 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 semble plus propre, cela ne fonctionne pas . La raison en étant que la méthode evil form->handleRequest()
n'utilise pas les méthodes setter du modèle pour mettre à jour les données (creuser dans form->setData()
pour plus détail).
La solution de contournement que j'ai utilisée était un LifeCycleCallback
. Toujours en attente de voir s'il y a plus de 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 le faire en utilisant xml aussi bien:
<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>
Fonctionne aussi pour moi sur une base de données mysql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Voici comment je l'ai résolu pour moi-même. Voici un exemple D'entité avec la valeur par défaut pour MySQL. Cependant, cela nécessite également l'installation d'un constructeur dans votre entité, et pour vous de définir la valeur par défaut là.
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'
Rien de tout cela n'a fonctionné pour moi. J'ai trouvé de la documentation sur le site de doctrine qui dit de définir la valeur directement 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 yaml pour votre entité, ce qui suit fonctionne 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
Ajouter à @romanb réponse brillante.
Cela ajoute un peu de surcharge dans la migration, car vous ne pouvez évidemment pas créer un champ avec une contrainte not null 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 avez-vous besoin de la valeur par défaut dans la base de données en premier lieu? Et généralement, il s'agit de permettre la création d'objets avec une contrainte not null.
J'ai lutté avec le même problème. Je voulais avoir la valeur par défaut de la base 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";
Bien que la définition de la valeur dans le constructeur fonctionnerait, l'utilisation des événements de cycle de vie de Doctrine pourrait être une meilleure solution.
En tirant parti de l'événement prePersist
Lifecycle, vous pouvez définir votre valeur par défaut sur votre entité uniquement sur la persistance initiale.
Soyez prudent lorsque vous définissez des valeurs par défaut sur la définition de la propriété! Faites-le dans le constructeur à la place, pour le garder sans problème. Si vous le définissez sur la définition de la propriété, conservez l'objet dans la base de données, puis effectuez une charge partielle, puis les propriétés non chargées auront à nouveau la valeur par défaut. C'est dangereux si vous voulez persister à nouveau l'objet.