Doctrine ORM关联的默认值

I have the entity (such as below). I want to set some default values while creating. As you can see in __construct, it is easy to set the $name (string), but how can I set the $group? (for example I know that there is a group in database with id=122)

/**
 * @ORM\Entity
 */
class Person {
    private $id;

    /** @ORM\Column(type="string") */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="Group", inversedBy="persons")
     * @ORM\JoinColumn(referencedColumnName="id")
     */
    private $group;

    public function setGroup(Group $group)
    {
        $this->group = $group;
        $group->addPerson($this);
    }

    // ... setters/getters

    //construct default Person
    public function __construct()
    {
        $this->setName("Mike");
        $this->setGroup($EXISTING_GROUP_FROM_MY_DB); // <<--------------
    }
}

I agree with moonwave99 that this is poor design. Here you are trying to access the database (through the Doctrine service) from a place that is not container-aware (i.e. it does not, and should not, know about Doctrine).

I had a similar issue recently... pretty much the same exact issue, actually. But I didn't want this logic to be inside the controller. So I wrote a service to take care of the User creation. And I gave that service access to the only other service it needed: Doctrine.

Here's an example, where a User is created with all available Roles:

namespace MyBundle\Entity;

class UserFactory
{
    private $doctrine;

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

    public function generateNewUser($email, $password)
    {
        $user = new User();

        // Since you have access to the Doctrine service, you can use $this->doctrine
        // to do anything you would normally do in your controller with $this->getDoctrine()
        $roles = $this->doctrine->getEntityManager()->getRepository("MyBundle:Role")->findAll();

        foreach ($roles as $role)
        {
            $user->addRole($role);
        }

        return $user;
    }
}

Now register that service in config.yml or services.yml, remembering to pass the Doctrine service to it:

services:
    mybundle.factory.user:
        class: MyBundle\Entity\UserFactory
        arguments: ['@doctrine']

And that's it... Now, in your controller, you can create a new User by doing:

public function MyController()
{
    $user = $this->get("mybundle.factory.user")->generateNewUser("someone@email.com", "password123");
}

Another method is to use either Lifecycle Callbacks in the entity or an Event Listener to do more complex functionality.

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class Person 
{
     const DEFAULT_GROUP = '122';

     /** @ORM\Column(type="string") */
     private $name = 'Mike';

    /**
     * @ORM\ManyToOne(targetEntity="Group", inversedBy="persons")
     * @ORM\JoinColumn(referencedColumnName="id")
     */
    private $group = self::DEFAULT_GROUP;

    //....

    public function setGroup(Group $group)
    {
        $this->group = $group;
        $group->addPerson($this);
    }

    /**
     * @param LifecycleEventArgs $event
     * @ORM\PrePersist
     */
    public function onPrePersist(LifecycleEventArgs $event)
    {
       if (!$this->group instanceof Group) {
           /** set default group if not specified */
           $group = $event->getEntityManager()->find('MyBundle:Group', $this->group ?: self::DEFAULT_GROUP);
           $this->setGroup($group);
       }
    }

}

Now when you persist a Person entity it will add the group if it was not explicitly set in the controller.

$person = new Person;
echo $person->getName(); //outputs: Mike
$person->setName('Foo Bar');
$em->persist($person); //persist or do nothing if already persisted
$group = $person->getGroup();
$groupPerson = $group->getPerson();
echo $group->getId(); //outputs: 122
echo $groupPerson->getName(); //outputs: Foo Bar
$em->flush(); //save to database

For sanity here are the links to the docs for the doctrine events: