Как запретить EntityType отображать текущий объект в отношении ManyToOne к тому же Entity (Parent)? - PullRequest
0 голосов
/ 08 апреля 2019

У меня есть сущность с отношением ManyToOne к себе, поскольку ее объекты могут иметь родителей одного и того же вида.

Я расширил EntityType, чтобы отобразить объекты из сущности, но яне хочу, чтобы текущий объект отображался в списке выбора, поскольку объект не может быть родительским для самого себя.

Чтобы отфильтровать объект по его владельцу, я делаю что-то вроде этого

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefault('query_builder', function (Options $options) {
        return function (EntityRepository $er) use ($options) {
            return $er->createQueryBuilder('con')
                ->orderBy('con.name', 'ASC')
                ->andWhere('con.owner = :owner')
                ->setParameter('owner', $this->getLoggedUser());
        };
    });
}

Но я понятия не имею, как заставить текущий объект добавить предложение andWhere, чтобы удалить его из списка выбора.

Итак, любая идея, как я могу удалить редактируемый объект изсписок выбора в EntityType?

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Спасибо michał-tomczuk и спасибо jakumi , вы оба были очень полезны, но я думаю, что ваши предложения не сработали, потому что FormType создан до AdminType и«данные» пока недоступны в настройках контекста.По крайней мере, я нигде не смог его найти.

Я попробовал другой подход, который сработал, даже если это своего рода излишество.

Поскольку тип формы всегда используется в контексте редактирования, а в моем случаеВ области действия SonataAdmin я ввел маршрутизатор в тип и отфильтровал запрос по идентификатору объекта, который мне удалось получить из PathInfo:

<?php
use Symfony\Component\Routing\RouterInterface;

/** @var RouterInterface $router */
private $router;  


/** {@inheritdoc} */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefault('query_builder', function (Options $options) {
        return function (EntityRepository $er) use ($options) {
            $matches = [];
            preg_match(
                '/^.*\/([0-9a-z\-]+)\/edit$/',
                $this->router->getContext()->getPathInfo(),
                $matches
            );

            $queryBuilder = $er->createQueryBuilder('ent')
                ->orderBy('ent.name', 'ASC')
            if (true === array_key_exists('1', $matches)) {
                $queryBuilder
                    ->andWhere('ent.id != :id')
                    ->setParameter('id', $matches[1]);
            }
            return $queryBuilder;
        };
    });
}

Я знаю, что это грязное решение, но оно работает.

0 голосов
/ 08 апреля 2019

Для исправления вашего текущего кода вы можете использовать $options['data'], так как он содержит базовые данные формы. Я верю, что в вашем случае это будет (например) Folder сущность. Попробуйте это (обратите внимание, что здесь я предполагаю, что базовая сущность сохраняется):

$resolver->setDefault('query_builder', function (Options $options) {
    return function (EntityRepository $er) use ($options) {
        return $er->createQueryBuilder('con')
            ->orderBy('con.name', 'ASC')
            ->andWhere('con != :current')
            ->andWhere('con.owner = :owner')
            ->setParameter('current', $options['data'])
            ->setParameter('owner', $this->getLoggedUser())
        ;
    };
});

Если базовая сущность еще не сохранена (например, при добавлении новой Folder), вам необходимо немного изменить код, чтобы учесть это:

$resolver->setDefault('query_builder', function (Options $options) {
    return function (EntityRepository $er) use ($options) {
        $qb = $er->createQueryBuilder('con')
            ->andWhere('con.owner = :owner')
            ->setParameter('owner', $this->getLoggedUser())
            ->orderBy('con.name', 'ASC')
        ;

        $current = $options['data'];
        if (null !== $current->getId()) {
            $qb
                ->andWhere('con != :current')
                ->setParameter('current', $options['data'])
            ;
        }

        return $qb;
    };
});

Надеюсь, это поможет.

...