Default value in Doctrine

PhpOrmDoctrine Orm

Php Problem Overview


How do I set a default value in Doctrine 2?

Php Solutions


Solution 1 - Php

<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
     */
    private $myColumn;
    ...
}

Note that this uses SQL DEFAULT, which is not supported for some fields like BLOB and TEXT.

Solution 2 - Php

Database default values are not "portably" supported. The only way to use database default values is through the columnDefinition mapping attribute where you specify the SQL snippet (DEFAULT cause inclusive) for the column the field is mapped to.

You can use:

<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}

PHP-level default values are preferred as these are also properly available on newly created and persisted objects (Doctrine will not go back to the database after persisting a new object to get the default values).

Solution 3 - Php

Set up a constructor in your entity and set the default value there.

Solution 4 - Php

Use:

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

and not:

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

For instance:

/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo

Solution 5 - Php

##Update

One more reason why read the documentation for Symfony will never go out of trend. There is a simple solution for my specific case and is to set the field type option empty_data to a default value.

Again, this solution is only for the scenario where an empty input in a form sets the DB field to null.

###Background

None of the previous answers helped me with my specific scenario but I found a solution.

I had a form field that needed to behave as follow:

  1. Not required, could be left blank. (Used 'required' => false)
  2. If left blank, it should default to a given value. For better user experience, I did not set the default value on the input field but rather used the html attribute 'placeholder' since it is less obtrusive.

I then tried all the recommendations given in here. Let me list them:

  • Set a default value when for the entity property:

<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}
  • Use the options annotation:

@ORM\Column(name="foo", options={"default":"foo bar"})
  • Set the default value on the constructor:

/**
 * @Entity
 */
class myEntity {
    ...
    public function __construct()
    {
        $this->myColumn = 'myDefaultValue';
    }
    ...
}

####None of it worked and all because of how Symfony uses your Entity class.

###IMPORTANT Symfony form fields override default values set on the Entity class. Meaning, your schema for your DB can have a default value defined but if you leave a non-required field empty when submitting your form, the form->handleRequest() inside your form->isValid() method will override those default values on your Entity class and set them to the input field values. If the input field values are blank, then it will set the Entity property to null.

http://symfony.com/doc/current/book/forms.html#handling-form-submissions

###My Workaround Set the default value on your controller after form->handleRequest() inside your form->isValid() method:

...
if ($myEntity->getMyColumn() === null) {
    $myEntity->setMyColumn('myDefaultValue');
}
...

Not a beautiful solution but it works. I could probably make a validation group but there may be people that see this issue as a data transformation rather than data validation, I leave it to you to decide.


Override Setter (Does Not Work)

I also tried to override the Entity setter this way:

...
/**
 * Set myColumn
 *
 * @param string $myColumn
 *
 * @return myEntity
 */
public function setMyColumn($myColumn)
{
    $this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;

    return $this;
}
...

This, even though it looks cleaner, it doesn't work. The reason being that the evil form->handleRequest() method does not use the Model's setter methods to update the data (dig into form->setData() for more details).

Solution 6 - Php

The workaround I used was a LifeCycleCallback. Still waiting to see if there is any more "native" method, for instance @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');
}

Solution 7 - Php

You can do it using xml as well:

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

Solution 8 - Php

Here is how I solved it for myself. Below is an Entity example with default value for MySQL. However, this also requires the setup of a constructor in your entity, and for you to set the default value there.

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'

Solution 9 - Php

None of this worked for me. I found some documentation on doctrine's site that says to set the value directly to set a default value.

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/faq.html#how-can-i-add-default-values-to-a-column

private $default = 0;

This inserted the value I wanted.

Solution 10 - Php

Works for me on a mysql database also:

Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: integer
            nullable: true
            options:
                default: 1

Solution 11 - Php

Adding to @romanb brilliant answer.

This adds a little overhead in migration, because you obviously cannot create a field with not null constraint and with no default value.

// 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");

With this answer, I encourage you to think why do you need the default value in the database in the first place? And usually it is to allow creating objects with not null constraint.

Solution 12 - Php

If you use yaml definition for your entity, the following works for me on a postgresql database:

Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: boolean
            nullable: false
            options:
                default: false

Solution 13 - Php

Here is how to do it in PHP 8 using attributes.

#[ORM\Column(type: 'boolean', nullable: false, options: ['default' => 0])]
#[Assert\NotNull()]
private bool $isFavorite = false;

Solution 14 - Php

While setting the value in the constructor would work, using the Doctrine Lifecycle events might be a better solution.

By leveraging the prePersist Lifecycle Event, you could set your default value on your entity only on initial persist.

Solution 15 - Php

I struggled with the same problem. I wanted to have the default value from the database into the entities (automatically). Guess what, I did it :)

<?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";

Solution 16 - Php

Be careful when setting default values on property definition! Do it in constructor instead, to keep it problem-free. If you define it on property definition, then persist the object to the database, then make a partial load, then not loaded properties will again have the default value. That is dangerous if you want to persist the object again.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJiew MengView Question on Stackoverflow
Solution 1 - Phpiv3ndyView Answer on Stackoverflow
Solution 2 - PhpromanbView Answer on Stackoverflow
Solution 3 - PhpJeremy HicksView Answer on Stackoverflow
Solution 4 - PhpStanislav TerletskyiView Answer on Stackoverflow
Solution 5 - PhpCallistinoView Answer on Stackoverflow
Solution 6 - PhpJiew MengView Answer on Stackoverflow
Solution 7 - PhpAndrew ZhilinView Answer on Stackoverflow
Solution 8 - PhpPutnaView Answer on Stackoverflow
Solution 9 - Phpmetric152View Answer on Stackoverflow
Solution 10 - PhpAlex HoangView Answer on Stackoverflow
Solution 11 - PhpDziamidView Answer on Stackoverflow
Solution 12 - PhpwonzbakView Answer on Stackoverflow
Solution 13 - PhpGigolNftView Answer on Stackoverflow
Solution 14 - PhptirunculaView Answer on Stackoverflow
Solution 15 - PhpSteffen BremView Answer on Stackoverflow
Solution 16 - PhptomazahlinView Answer on Stackoverflow