我在一个应用程序中使用ApiPlatform。我刚刚关注了这个https://api-platform.com/docs/core/filters/#using-doctrine orm过滤器,根据登录的用户添加一个额外的过滤器。
这样做的目的是让用户只能看到自己的资源,而且效果很好,因为我使用TokenStorageInterface获得了当前登录用户的id。
但是,当您想过滤用户实体中存储的数据之外的其他内容时,如何做到这一点?我不想做额外的SQL查询来检索所需的值。事实上,有时当ApiPlatform检索资源时,您不能使用过滤器,因为它缺少联接。因此,我想通过添加一个额外的INNER JOIN来更改ApiPlatform生成的查询。
对这些表格和相关资源进行成像:
- user:/api/users[/{id}]
- booking:/api/bookings[/{id}]
- booking_comments:/api/booking/comments[/{id}]
我希望用户只检索其信息。有了UserAware类,在User和Booking上很容易做到这一点,因为您拥有登录用户的userId。但是,为了防止有人阅读与另一个用户相关的预订评论,我没有找到正确的方法,而在booking.id=booking_commments.booking_id WHERE booking.user_id=%s上添加一个额外的内部联接则很简单。
booking_comments表没有user_id字段,我不想将其添加到数据库中。我也不想使用DataProvider来构建自定义查询(这是我迄今为止所做的,我认为这不是当前的技术状态(。
我刚刚发现Doctrine过滤器与您的问题有关,但在我看来,它们不适合您的需求,因为Api平台利用了自己的扩展系统,该系统在安全页面中提到,正是您想要做的:过滤与当前用户有关的结果集。此外,它可以让您更好地控制过滤(当前资源是什么?当前操作是什么?等等(。
过滤所有Booking和BookingComment URL的结果集的一个简单示例:
class BookingExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
{
/** @var Security */
private $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
{
$this->filterResultSet($queryBuilder, $resourceClass);
}
public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = [])
{
$this->filterResultSet($queryBuilder, $resourceClass);
}
private function filterResultSet(QueryBuilder $queryBuilder, string $resourceClass)
{
switch ($resourceClass) {
case BookingComment::class:
$comment = $queryBuilder->getRootAliases()[0];
$booking = 'booking';
$queryBuilder->innerJoin("$comment.booking", $booking);
// do not break here !
case Booking::class:
$booking = $booking ?? $queryBuilder->getRootAliases()[0];
$queryBuilder->innerJoin("$booking.user", 'user');
$queryBuilder->andWhere(':user = user');
$queryBuilder->setParameter(':user', $this->security->getUser());
}
}
}
请注意,此示例认为匿名用户是被禁止的。