Skip to content
Advertisement

Doctrine : Default value on joinColumn field

New to symfony2 and Doctrine.

How can I set a default value to the field foo_id (which is a reference on Foo table) to point on the ID 1 of the Foo table (which exists in all cases) ?

MeNavigationBundleEntityPublicText:
    type: entity
    table: public_text
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        title:
            type: string
            length: '255'
            nullable: false
        content:
            type: string
            length: '2000'
            nullable: false            
    manyToOne:
        foo:
            #How to set a default value???
            targetEntity: MeNavigationBundleEntityFoo
            joinColumn:
                name: foo_id
                referencedColumnName: id   
                nullable: false 
    lifecycleCallbacks: {  }

I tried a lot of things without success :

  • Set default value to ID 1 in the constructor of Foo
  • Perform a request to retrieve the Foo object of ID 1 in the Me entity (could works, but bad practice)

Advertisement

Answer

Please note that using columnDefinition alone will work for generating migrations but will break the ORM context and potentially cause FK integrity issues. You will still need to add the object association to the ORM for persisting entities. See warnings from Ocramius

Example:

(new PublicText())
    ->getFoo(); //null - expected object(Foo)#1 (1) { ["id"] => int(1) }

I have seen many ways to achieve this in doctrine 2.

Constructor

In general, the quickest way and what most users do is require an association in the constructor.

public function __construct(Foo $foo)
{
   $this->foo = $foo;
}

Then you can use getReference to retrieve it in your controller without needing to query the database. See http://doctrine-orm.readthedocs.org/en/latest/reference/advanced-configuration.html#reference-proxies

$foo = $em->getReference('app:Foo', 1);
$text = new PathToEntityPublicText($foo);
$em->persist($text);
$em->flush();

LifeCycleEvents

My preferred way Another method to set the default value with most ManyToOne relationships is to utilize the LifeCycleEvents http://doctrine-orm.readthedocs.org/en/latest/reference/events.html

Though it does have some caveats to be aware of. So be sure to RTM before implementing into production environments. In this case it should work fine, but I don’t know your entire mapping structure.

 use DoctrineORMEventLifecycleEventArgs;

/**
 * @Entity
 * @HasLifeCycleEvents
 */
class PublicText
{
    // ...

    /**
     * @PrePersist
     * @param DoctrineORMEventLifecycleEventArgs $event
     */
    public function onPrePersist(LifecycleEventArgs $event)
    {
        if (false === empty($this->foo)) {
           return;
        }
        $this->foo = $event->getEntityManager()->getReference('app:Foo', 1);
    }
}

Then in your controller.

$text = new PathToEntityPublicText;
$em->persist($text); //retrieve and set foo if not set in the Entity Event.
$em->flush();

Repository Method

Another option within your Entity is to just set the property’s value using a Repository.

Define Repository Class in Entity

/**
 * @Entity(repositoryClass="PublicTextRepo")
 */
class PublicText
{
    // ...
}

Repository

use DoctrineORMEntityRepository;

class PublicTextRepo extends EntityRepository
{
   public function create()
   {
       $text = new PathToEntityPublicText;
       $foo = $this->_em->getReference('app:Foo', 1);
       $text->setFoo($foo );
       return $text;
   }
}

Then in your controller you can then do

$text = $em->getRepository('app:PublicText')->create();
$em->persist($text);
$em->flush();

Discriminator Map

Though not always viable depending on the use case. One of the ways I go about defining a default value of an Entity is creating a DiscriminatorMap with single table inheritance. http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance.

This way when the object is created the default value is automatically set in the database, and locks the object as that type. The issue is that the resulting value is not an object like it is in the other methods above.

To get the object’s discriminator static value, you can use constants within the objects you define.

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @Table(name="user")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({Person::TYPE="Person", Employee::TYPE="Employee"})
 */
class Person
{
    const TYPE = 'person';     

    /**
     * @return string [person|employee]
     */   
    public function getType()
    {
        return $this::TYPE;
    }
    // ...
}

/**
 * @Entity
 */
class Employee extends Person
{
    const TYPE = 'employee';
    // ...
}

Then all you need to do in your controller is.

$employee = new PathToEntityEmployee;
$em->persist($employee); //inserts with `user.type` as `employee`
$em->flush();

echo $employee->getType(); //employee
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement