Slim 3.11 可调用解析器类型错误

Slim 3.11 Callable Resolver TypeError

我找不到我的错误。当我在我的 slim api 中尝试一条路线时,我得到了 follow TypeError。 错误是:

Argument 1 passed to HCC\API\Controllers\FacultyController::__construct() must be an instance of PDO, instance of Slim\Container given

此控制器的构造函数是:

public function __construct(\PDO $db, \MongoDB\Client $mongo, \Monolog\Logger $applogger, \Monolog\Logger $seclogger)

我放入容器的DI工厂是:

$container['FacultyController'] = function($c) {
    return new FacultyController($c->get('db'), $c->get('mongo'), $c->get('appLogger'), $c->get('secLogger'));
};

我试过将每个设置为它自己的变量并传入这些变量但效果相同。我已经 运行 一个成功的测试,它只加载了 slim 应用程序并检查容器是否有一个对象 class FacultyController 并且它有消息说我有一个那个控制器所以我 99% 确定控制器实际上被放入容器中。我认为路线可能有问题。我在控制器中有一个与考试相同的构造和调用方法。

我在其他帖子中发现了这个错误,但我发现的是没有将某些东西传递给构造方法的问题,这似乎是传递给我的错误参数。

我不想将整个容器传递给每个控制器,因为这些控制器只需要设置依赖项,而就控制器而言,其中有很多不必要的项目。

这主要是因为 Slim 在依赖容器中找不到 HCC\API\Controllers\FacultyController class(因为你用字符串 'FacultyController' 而不是 class 的完全限定名称注册了它) .

当 Slim 在依赖容器中找不到它时,默认情况下,Slim 会尝试自己创建 HCC\API\Controllers\FacultyController 并将容器实例传递给 FacultyController 构造函数。但是因为你用 PDO class 的类型提示声明 FacultyController 的构造函数,PHP 抱怨这种类型不匹配。

解决方案是尝试将 'FacultyController' 替换为包含命名空间的全名,以使 Slim 可以在依赖容器中找到控制器。

因此,

$container['FacultyController'] = function($c) {
     return new FacultyController(
         $c->get('db'), 
         $c->get('mongo'), 
         $c->get('appLogger'), 
         $c->get('secLogger')
     );
};

你应该使用

$container[\HCC\API\Controllers\FacultyController::class] = function($c) {
     return new \HCC\API\Controllers\FacultyController(
         $c->get('db'), 
         $c->get('mongo'), 
         $c->get('appLogger'), 
         $c->get('secLogger')
     );
};

use \HCC\API\Controllers\FacultyController;

$container[FacultyController::class] = function($c) {
     return new FacultyController(
         $c->get('db'), 
         $c->get('mongo'), 
         $c->get('appLogger'), 
         $c->get('secLogger')
     );
};

然后在你的路由声明中,你可以使用,例如:

$app->get('/faculty', \HCC\API\Controllers\FacultyController::class); 

More information about ::class

更新

如果您使用上面的代码,FacultyController 被认为是可调用的 class,这意味着它应该实现 __invoke() 方法。

class FacultyController 
{
    public function __invoke($request, $response, $args)
    {
          //handle the request
    }
}

如果不想使用invokableclass而是使用普通方法来处理请求,在设置路由时包含方法名

$app->get('/faculty', \HCC\API\Controllers\FacultyController::class . ':getFacultyCollection');

getFacultyCollection() 方法将被调用来处理请求。

class FacultyController 
{
    public function getFacultyCollection($request, $response, $args)
    {
          //handle the request
    }
}

如果 getFacultyCollection() 调用导致应用程序崩溃,如您在评论中所说,那么这是完全不同的问题。也许你有未终止的循环?

More information about __invoke() magic method