Symfony 4、如何实现通用控制器即服务?

2023-12-15

我有这个控制器

Controller1.php

<?php


namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class file1Controller extends AbstractController
{
    /**
     * @Route("/Some/URI", methods={"GET"})
     * @param Request $request
     * @return JsonResponse
     */
    public function list(Request $request)
    {
        if (empty($request->headers->get('api-key'))) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if ($request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->getDoctrine()->getRepository('App:Something')->findAll());
    }
}

其工作原理完全符合预期(使用 Postman 和我的浏览器对其进行了测试)。我想概括地将通用控制器作为服务并为每个控制器使用该服务,Controller1.php, Controller2.php and Controller3.php除了@routeSomething方法内部getRepository.

这是我的尝试:

GeneralService.php

<?php


namespace Service;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;


class GeneralService
{
    /**
     * @param Request $request
     * @param String $entity
     * @return JsonResponse
     */
    public function list(Request $request, String $entity)
    {
        if (empty($request->headers->get('api-key'))) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if ($request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->getDoctrine()->getRepository('App:{$entity}')->findAll());
    }

}

And Controller1.php然后更改为SubscriptionController.php:

<?php


namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Service\GeneralService;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class SubscriptionController extends AbstractController
{
    /**
     * @Route("/Some/Uri", methods={"GET"})
     * @param GeneralService $generalService
     * @param Request $request
     * @return JsonResponse
     */
    public function AuthenticateAPI(GeneralService $generalService, Request $request)
    {
        $AuthenticatorObject = $generalService->list($request ,'Something');
        return $AuthenticatorObject;
    }

}

不幸的是,这不起作用并产生以下错误:

无效参数异常

无法确定“App\Controller\Controller1::AuthenticateAPI()”的控制器参数:$generalService 参数的类型暗示为不存在的类或接口:“Service\GeneralService”。

我不明白这个错误从何而来,也不明白为什么会发生。有人可以帮助我理解为什么会出现这种情况以及如何解决它吗?


好的。回到基础知识。首先为自己准备一个 IDE,例如 PHPStorm。它将突出显示各种语法错误以及其他错误。特别是,IDE 将帮助解决服务命名空间问题以及各种其他问题。

依赖注入背后的基本概念是给定类所需的依赖应该被注入。您的 GeneralService 类需要实体管理器。在您之前的相同问题中,您有 GeneralService 扩展了 AbstractController,因为 AbstractController 有一个 getDoctrine 方法。它仍然不起作用,因为 getDoctrine 又需要服务容器。当然,在您当前的代码中,GeneralService 根本没有 getDoctrine 方法。

无论如何,由于 GeneralService 需要实体管理器,然后注入它:

# src/Service/GeneralService.php
namespace App\Service; # NOTE App\Service not just Service

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class GeneralService
{
    private $entityManager;

    // Let Symfony inject whatever dependencies are needed
    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }
    public function list(Request $request, String $entityClass) : JsonResponse
    {
        if (!$request->headers->has('api-key')) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if (!$request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->entityManager->getRepository($entityClass)->findAll());
    }
}

并且不要再排除一般服务人员。

一旦您使用 IDE 消除了所有小语法错误,您的控制器类就几乎没问题了:

namespace App\Controller;

use App\Service\GeneralService;
use App\Entity\SomeEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

class SubscriptionClass extends AbstractController
{
    public function AuthenticateAPI(Request $request, GeneralService $generalService)
    {
        $AuthenticatorObject = $generalService->list($request,SomeEntity::class);
        return $AuthenticatorObject;
    }

}

我实际上并没有测试上面的代码,尽管它应该让您至少更进一步。

最后一点:不要直接访问任何超级全局变量,即 $_ENV['API_KEY'] 是不行的。 api_key 应与实体管理器一起注入。我将把确切的细节留给学生作为练习,因为注入字符串与注入对象有点不同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Symfony 4、如何实现通用控制器即服务? 的相关文章

随机推荐

  • 在 Switch Case 中声明 UI 对象

    我读过有关开关盒范围的内容 跳转标签等等 但是 SO 这里建议的解决方案似乎意味着添加花括号可以避免这个问题 然而 这似乎仍然不起作用 switch objectType case label label is an integer con
  • 删除NiFi中的空属性

    因为这个问题仍未解决 我有一个EvaluateJsonPath有时输出带有空字符串的属性的处理器 是否有直接的方法从流程文件中删除属性 我尝试使用UpdateAttributes处理器 但它只能根据匹配属性名称进行删除 我需要匹配属性的值
  • 类的事件监听器?

    我有一个引用 Id 的 EventListener 它运行良好 唯一的问题是我至少有十几个需要引用此 EventListener 的地方 所以我不想有十几个完全相同但具有不同 Id 的脚本 有没有办法让 EventListener 引用一个
  • 如何在谷歌地图上显示浮动视图,就像谷歌地图中的搜索栏一样

    我已经成功实现了地图 但我找不到任何与此相关的帮助 这是我对谷歌地图片段的实现 SupportMapFragment fragment private GoogleMap map FragmentManager fm Override pu
  • 将 UTF8 转换为 std::wstring 的跨平台方法 [重复]

    这个问题在这里已经有答案了 可能的重复 STL 中 UTF8 与宽字符的转换 我知道如何使用将 UTF8 转换为 std wstring多字节到宽字符 std wstring utf8to16 const char src std vect
  • 8086中的物理地址是如何产生的?

    In the 8086架构中 内存空间大小为 1 MiB 并分为每个最大 64 KiB 的逻辑段 即它有20地址线因此使用以下方法 数据段寄存器左移4位然后添加到偏移寄存器 我的问题是 尽管所有寄存器都只有 16 位 但我们如何进行移位操作
  • 刷新服务引用会更新app.config

    每次我对 WS 进行更改并更新 Visual Studio 中的引用时 VS 都会使用其他不必要的信息覆盖我的 app config 因此 当我之后启动客户端时 我收到此错误 处理标头时发现错误 代码生成器所做的更改是remove每个绑定中
  • Xpage, createForm=false 禁用链接上的 SSJS 事件?

    我问这个只是为了在这里澄清 我不小心将 createForm 属性设置为 false 然后我期望一个链接事件应该打开另一个页面 但不再起作用 这是 SSJS 事件的预期行为吗 当您禁用表单创建时在链接中 正如 Per 提到的 所有事件都需要
  • Windows 窗体 - 单击按钮将数据添加到列表视图[重复]

    这个问题在这里已经有答案了 我有一个 winform 应用程序 点击后会填充一些数据 button UpdateTS 如何添加存储在变量中的数据 单击该按钮后可用 我想要在列表视图中显示的数据存储在一个名为的数组中 results butt
  • 公开声明中“iostat”参数的含义是什么?

    我对打开文件中使用 iostat 参数感到困惑 如上所述 当 open 命令成功时 iostat 的值为 0 open unit 99 file vel zcor22 txt status old iostat ierr err 100 1
  • 结构体动态数组和函数调用 f(const struct_type *const data[])

    以下代码警告类型不兼容 解决此代码的正确方法是什么 thanks typedef struct a struct struct type void f const struct type const data unsigned n void
  • 如何使用(由 mod 重写驱动)漂亮的 URL 读取 $_GET 变量

    各位程序员大家好 我第一次使用很好的 URL 但我不太明白为什么我无法从脚本中读取 oAuth 响应 这是我的设置 htaccess RewriteCond REQUEST FILENAME f RewriteCond REQUEST FI
  • C# Winforms 线程:调用封闭表单

    下面的代码演示了我的困境 该代码创建一个后台线程来处理某些内容 然后使用结果调用 UI 线程 如果后台线程在窗体关闭后调用窗体上的 Invoke 则可能会引发异常 它在调用 Invoke 之前检查 IsHandleCreated 但表单可能
  • Python 多处理傻瓜教程 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我试图找到一个简单的示例 清楚地显示单个任务被划分为多处理 坦率地说 许多示例都过于复杂 从而使流程更难以使用 有人愿意分享他们的突破性样本或例子吗
  • Kendo UI 网格 - 如何绑定到子属性

    如何在 Kendo 网格的模型设置中将列 字段绑定到 json 结果的子属性 在 JavaScript 中 例如 我希望网格包含以下列 FName LName Street 和 Address 基本上我想展平 Web 服务返回的层次结构 剑
  • 在哪里可以找到 os.urandom() 的源代码?

    我想调查和研究python 3 7的代码os urandom 功能 我查看了各自的标准库os py 但它既没有在那里定义 也没有在那里导入 我还尝试 grep 查找定义 usr lib python3 7 grep rFl def uran
  • Java 录制/混合两个音频流

    我有一个java应用程序 它记录来自混音器的音频并将其存储在字节数组中 或将其保存到文件中 我需要的是同时从两个混音器获取音频 并将其保存到音频文件 我正在尝试使用 wav 问题是我可以获得两个字节数组 但不知道如何合并它们 合并 我并不是
  • Scala 编译器不使用 case 类的 unapply 方法来进行模式匹配,这是为什么?

    abstract class Animal case class Cat name String extends Animal case class Dog name String extends Animal 假设我定义了 Cat 和 D
  • jqGrid添加项目复选框字段默认为选中

    这是一个简单的问题 我有一个运行良好的 jqGrid 但我想设置一个复选框的默认值 以便在用户添加新项目时进行检查 这是一段代码 name Active index active width 80 align center sortable
  • Symfony 4、如何实现通用控制器即服务?

    我有这个控制器 Controller1 php