【问题标题】:How to hide item from collection depending on some field value?如何根据某些字段值从集合中隐藏项目?
【发布时间】:2020-03-22 16:18:12
【问题描述】:

我覆盖(自定义操作和服务)我的应用程序的 DELETE 操作以避免从数据库中删除数据。我要做的是更新一个字段值:isDeleted === true

这是我的控制器:

class ConferenceDeleteAction extends BaseAction
{
    public function __invoke(EntityService $entityService, Conference $data)
    {
        $entityService->markAsDeleted($data, Conference::class);
    }

...

我的服务:

class EntityService extends BaseService
{
    public function markAsDeleted(ApiBaseEntity $data, string $className)
    {
        /**
         * @var ApiBaseEntity $entity
         */
        $entity = $this->em->getRepository($className)
            ->findOneBy(["id" => $data->getId()]);
        if ($entity === null || $entity->getDeleted()) {
            throw new NotFoundHttpException('Unable to find this resource.');
        }

        $entity->setDeleted(true);
        if ($this->dataPersister->supports($entity)) {
            $this->dataPersister->persist($entity);
        } else {
            throw new BadRequestHttpException('An error occurs. Please do try later.');
        }
    }

}

如何在 GET 动词上从集合中隐藏“已删除”项目(从结果中过滤它们以使其不可见)?

这是我对 GET 动词的操作,我不知道如何处理:

class ConferenceListAction extends BaseAction
{
    public function __invoke(Request $request, $data)
    {
        return $data;
    }
}

【问题讨论】:

    标签: symfony doctrine api-platform.com soft-delete


    【解决方案1】:

    我做了什么;我不确定这是最佳实践。

    从我们做的时候开始:

    return $data;
    

    在我们的控制器中,API Platform 已经获取数据并使用 $data 填充。 所以我决定在返回之前添加我的逻辑;喜欢:

        public function __invoke(Request $request, $data)
        {
            $cleanDatas = [];
            /**
             * @var Conference $conf
             */
            foreach ($data as $conf) {
                if (!$conf->getDeleted()) {
                    $cleanDatas[] = $conf;
                }
            }
    
            return $cleanDatas;
        }
    

    所以现在我只有未删除的项目。如果有更好的,请随时告诉我。

    谢谢。

    【讨论】:

      【解决方案2】:

      the docs 不鼓励自定义控制器。您正在使用 Doctrine ORM,因此您可以使用自定义 Doctrine ORM 扩展:

      // api/src/Doctrine/ConferenceCollectionExtension.php
      
      namespace App\Doctrine;
      
      use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
      use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
      use App\Entity\Conference;
      use Doctrine\ORM\QueryBuilder;
      
      final class CarCollectionExtension implements QueryCollectionExtensionInterface
      {
          public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
          {
              if ($resourceClass != Conference::class) return;
      
               $rootAlias = $queryBuilder->getRootAliases()[0];
               $queryBuilder->andWhere("$rootAlias.isDeleted = false OR $rootAlias.isDeleted IS NULL);
          }
      }
      

      这将自动与使用方法 GET 的集合操作的任何过滤器、排序和分页组合。

      您可以通过在 if 语句中添加如下内容来使此扩展特定于某个操作:

      || $operationName == 'conference_list'
      

      如果您不使用自动配置,则必须注册自定义扩展:

      # api/config/services.yaml
      services:
      
          # ...
      
          'App\Doctrine\ConferenceCollectionExtension':
              tags:
                  - { name: api_platform.doctrine.orm.query_extension.collection }
      

      如果您还想为项目操作添加标准,请参阅the docs on Extensions

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-10
        • 1970-01-01
        • 2016-06-17
        • 2012-05-07
        • 1970-01-01
        相关资源
        最近更新 更多