Как отфильтровать результаты по связанному свойству в Api-Platform? - PullRequest
0 голосов
/ 10 января 2020

У меня есть User Сущность и Organisation сущность, существует связь ManyToOne между Booking и User:

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="bookings")
 * @ORM\JoinColumn(nullable=false)
 */
private $user;

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

collectionOperations={
*          "get"={
*              "access_control"="object.getUser().getOrganisation() == user.organisation"
*              "normalization_context"={
*                  "groups"={"read"}
*              }
*          },

, конечно, это не работает.

Я знаю, что могу фильтровать передаваемые параметры в строке запроса, но мне нужно, чтобы эти результаты не фильтровались на стороне API, а не клиентом.

1 Ответ

1 голос
/ 10 января 2020

На странице Безопасность документов написано:

Фильтрация коллекций в соответствии с ролью или разрешениями текущего пользователя должна выполняться непосредственно на уровне поставщика данных. Например, при использовании встроенных адаптеров для Doctrine ORM, MongoDB и ElasticSearch удаление записей из коллекции должно выполняться с использованием расширений.

Просмотр расширений , вам нужно будет сделать что-то вроде:

final class BookingOwnerExtension implements QueryCollectionExtensionInterface
{
    private $security;

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

public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
    {
        if (Booking::class !== $resourceClass || $this->security->isGranted('ROLE_ADMIN') || null === $user = $this->security->getUser()) {
            return;
        }

        $organization = $user->getOrganization()

        $rootAlias = $queryBuilder->getRootAliases()[0];
        $queryBuilder
            ->leftJoin(sprintf('%s.user', $rootAlias), 'u')
            ->andWhere('user.organization = :organization')
            ->setParameter('organization', $organization);
    }
}

(Точный запрос будет зависеть от того, что вы намерены делать, так как я не знаком с вашим приложением, я могу только указать вам правильное направление. Но это просто добавление соответствующих условий к запросу с использованием построителя запросов.)

Скорее всего, этого достаточно, хотя, если вы не используете автоконфигурацию, вам придется зарегистрировать пользовательское расширение с соответствующими тегами:

# api/config/services.yaml
services:
    # ...

    'App\Doctrine\BookingOwnerExtension':
        tags:
            - { name: api_platform.doctrine.orm.query_extension.collection }
...