将所有结果限制为特定的 属性 值(即 active=true)

Restrict all results to a specific property value (i.e. active=true)

我在 API 平台上使用 Symfony 4。

我有一个 Project 实体,它有一个布尔值 active 属性。

我公开的 API 应该只显示活动项目。

如何将在 /api/projects 检索到的所有结果限制为 active 值为 true 的记录?

<?php
/**
 * @ApiResource(
 *     attributes={
 *     "normalization_context"={"groups"={"read"}},
 *     "denormalization_context"={"groups"={"write"}}
 *   },
 *   collectionOperations={"get"},
 *   itemOperations={"get"}
 * )
 * @ORM\Entity(repositoryClass="App\Repository\ProjectRepository")
 * @ORM\Table(name="project")
 */
class Project
{

    /**
     * @var int
     *
     * @Groups({"read"})
     * @ORM\Id
     * @ORM\Column(type="integer", options={"unsigned":true})
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var bool
     *
     * @ORM\Column(type="boolean", nullable=false)
     */
    private $active = false;

    ...
}

解决方案是使用 Doctrine 扩展:https://api-platform.com/docs/core/extensions/#extensions

添加 class 和服务到位后,where 子句被注入 Project 集合和项目查询。

src/Doctrine/ProjectAcctiveExtension.php

<?php

namespace App\Doctrine;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;

class ProjectActiveExtension implements QueryCollectionExtensionInterface
{
    /**
     * {@inheritdoc}
     */
    public function applyToCollection(
        QueryBuilder $qb,
        QueryNameGeneratorInterface $queryNameGenerator,
        string $resourceClass, string $operationName = null): void
    {
        $this->addWhere($qb, $resourceClass);
    }

    /**
     * {@inheritdoc}
     */
    public function applyToItem(
        QueryBuilder $qb,
        QueryNameGeneratorInterface $queryNameGenerator,
        string $resourceClass, array $identifiers,
        string $operationName = null,
        array $context = []): void
    {
        $this->addWhere($qb, $resourceClass);
    }

    /**
     * @param QueryBuilder $qb
     * @param string       $resourceClass
     */
    public function addWhere(QueryBuilder $qb, string $resourceClass): void
    {
        $rootAlias = $qb->getRootAliases()[0];
        $qb->andWhere(sprintf('%s.active = :active', $rootAlias));
        $qb->setParameter('active', true);
    }
}

services.yml

'App\Doctrine\ProjectActiveExtension':
    tags:
        - { name: api_platform.doctrine.orm.query_extension.collection, priority: 9 }
        - { name: api_platform.doctrine.orm.query_extension.item }