0

我正在尝试从与 Slim 捆绑在一起的 pimple 容器切换到 PHP-DI,但我遇到了让自动装配工作的问题。由于我仅限于使用 PHP 5.6,因此我使用 Slim 3.9.0 和 PHP-DI 5.2.0 以及 php-di/slim-bridge 1.1。

我的项目结构如下:

api
 - src
 |    - Controller
 |    |  - TestController.php
 |    - Service
 |    - Model
 |    - ...
 - vendor
 - composer.json

api/composer.json我有以下内容,然后运行composer dumpautoload

{
    "require": {
        "slim/slim": "3.*",
        "php-di/slim-bridge": "^1.1"
    },

    "autoload": {
        "psr-4": {
            "MyAPI\\": "src/"
        }
    }
}

我的api/src/Controller/TestController.php文件包含一个类:

<?php
namespace MyAPI\Controller;

class TestController
{ 
    public function __construct() 
    {
        
    }
    
    public function test($request,$response)
    {
        return $response->write("Controller is working");
    }
}

我最初尝试使用最小设置来使自动装配工作,只使用默认配置。index.php

<?php

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

require '/../../api/vendor/autoload.php';

$app = new \DI\Bridge\Slim\App;

$app->get('/', TestController::class, ':test');

$app->run();

但是,这返回了错误:

Type: Invoker\Exception\NotCallableException 
Message: 'TestController'is neither a callable nor a valid container entry

我可以让它工作的唯一两种方法是直接放置TestControllerindex.php(这让我觉得 PHP-DI 不能很好地与自动加载器一起使用)或使用\DI\Bridge\Slim\App. 但是,由于我需要显式注册控制器类,这有点违背了使用自动装配的意义(除非我错过了这一点):

use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use function DI\factory;

class MyApp extends \DI\Bridge\Slim\App
{
    public function __construct() {
        $containerBuilder = new ContainerBuilder;
        $this->configureContainer($containerBuilder);
        $container = $containerBuilder->build();

        parent::__construct($container);
    }
    protected function configureContainer(ContainerBuilder $builder)
    {
        $definitions = [
            'TestController' => DI\factory(function (ContainerInterface $c) {
            return new MyAPI\Controller\TestController();
        })
    ];
        $builder->addDefinitions($definitions);
    }
}
$app = new MyApp();

$app->get('/', ['TestController', 'test']);

$app->run();
4

1 回答 1

0

如果你想调用测试方法,语法是:

 $app->get('/', TestController::class .':test');
 // or 
 $app->get('/', 'TestController:test');

而不是

$app->get('/', TestController::class ,':test');

cf https://www.slimframework.com/docs/v3/objects/router.html#container-resolution

于 2021-09-02T12:47:13.160 回答