简体   繁体   中英

Remove already asscoiated values from choice list in sonata admin

I have an one to one relation in my sonata admin bundle.

Person <-> Player. 

If i go to my Person admin i can choose the player from the choice list.

If i go to another Person object the player (which is now already assigned) is shown again ... if i choose it, there occurs an error ...

The error is

Failed to update object: AppBundle\\Entity\\Person

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '18' for key 'UNIQ_9A5FDF45F6B75B26'

Can i change the behaviour that already assigned values do not appear in other objects?

I cant find a option for doing this in sonata admin

You can generate a custom choice list for every Person.

Add method to PlayerRepository:

class PlayerRepository extends EntityRepository
{
    public function getNotAssociatedPlayers($person)
    {
        $qb = $this->createQueryBuilder('p')
                   ->leftJoin('p.person', 'prsn')
                   ->where('prsn.id is null');
        if($person !== null)
        {
            $qb->orWhere('prsn.id = :person')
               ->setParameter('person', $person);
        }

        return $qb->getQuery()
                  ->getResult();
    }
}

And use it in PersonAdmin:

protected function configureFormFields(FormMapper $formMapper)
{
    $person = ($this->getSubject()->getPlayer() !== null)
              ? $this->getSubject()->getId()
              : null;
    $em = $this->getConfigurationPool()->getContainer()->get('doctrine.orm.entity_manager');
    $choices = $em->getRepository('YourBundle:Player')->getNotAssociatedPlayers($person);

    $formMapper
        ->add('player', null, array(
            'choices' => $choices,
        ));

Please, let me know if something went wrong with that.

EDIT:

Documented solution is a query_builder option for the field:

$formMapper
    ->add('player', null, array(
        'query_builder' => function(EntityRepository $er) 
        {
            $qb = $er->createQueryBuilder('p')
                     ->leftJoin('p.person', 'prsn')
                     ->where('prsn.id is null');
            if($this->getSubject()->getPlayer() !== null)
            {
                $qb->orWhere('prsn.id = :person')
                   ->setParameter('person', $this->getSubject()->getId());
            }
            return $qb;
        }
    ));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM