Valeur par défaut dans Doctrine

Comment définir une valeur par défaut dans Doctrine 2?

285
demandé sur Nathaniel Ford 2010-07-31 08:59:15

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).

347
répondu romanb 2013-05-07 17:04:28
<?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.

427
répondu iv3ndy 2018-01-12 10:03:16

Configurez un constructeur dans votre entité et définissez la valeur par défaut.

60
répondu Jeremy Hicks 2011-03-07 15:43:19

Utilisation:

options={"default":"foo bar"}

Et non:

options={"default"="foo bar"}

Par exemple:

/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
51
répondu Stanislav Terletskyi 2013-03-13 11:05:35

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:

  1. Non requis, peut être laissé en blanc. (Utilisé 'required' = > false)
  2. 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).

44
répondu Callistino 2016-11-08 18:26:09

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');
}
16
répondu Jiew Meng 2016-01-08 22:44:54

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>
11
répondu Andrew Zhilin 2017-07-28 11:42:51

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
7
répondu Alex Hoang 2016-01-08 22:43:40

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'
7
répondu Putna 2016-01-08 22:44:25

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.

4
répondu metric152 2016-05-17 16:24:19

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
3
répondu wonzbak 2013-09-12 09:15:15

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.

2
répondu Dziamid 2013-05-07 17:07:09

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";
1
répondu Steffen Brem 2013-07-12 22:57:13

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.

0
répondu tiruncula 2016-01-08 22:42:46

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.

0
répondu tomazahlin 2017-10-11 13:45:14