0

我来自 .net 和 DI/IOC 容器的世界,如 autofac、ninject 等。

我希望,andphp-di的文档似乎暗示以下内容应该有效:

index.php / 前端控制器

$containerBuilder = new DI\ContainerBuilder();
$containerBuilder->addDefinitions([

    ListRepositoryInterface::class => DI\get(ListRepository::class)
]);

$app = DI\Bridge\Slim\Bridge::create($container);

$app->get('/list', [HelloWorldController::class, 'get']);

$app->run();

有问题的“控制器即服务”:

/*
* HelloWorldController
*/
class HelloWorldController
{
    private $listRepository;

    public function __construct(ListRepositoryInterface $listRepository)
    {
        $this->listRepository = $listRepository;
    }

    public function get(Request $request, Response $response)
    {
        $lists = $this->listRepository->getAllForUser(0);
        $json = json_encode($lists);

        $response->getBody()->write($json);

        return $response;
    }
}

接口和实现,在一个代码块中为简洁起见:

interface ListRepositoryInterface
{
    public function getAllForUser($userId);
}

class ListRepository implements ListRepositoryInterface
{
    public function getAllForUser($userId) 
    {
        return [
                [
                    'name' => 'a list'
                ]
            ];
    }
}

当我用 php 开发服务器运行它并点击<addr>/list时,我得到(有几个换行符用于可视化和清理我的个人信息):

Fatal error: Uncaught DI\Definition\Exception\InvalidDefinition: Entry "ToDo\Controllers\HelloWorldController" cannot be resolved: Entry "Todo\DataAccess\Contracts\ListRepositoryInterface" 
cannot be resolved: the class is not instantiable Full definition: Object ( class = #NOT INSTANTIABLE# Todo\DataAccess\Contracts\ListRepositoryInterface lazy = false ) Full definition: Object ( class = ToDo\Controllers\HelloWorldController lazy = false 
__construct( $listRepository = get(Todo\DataAccess\Contracts\ListRepositoryInterface) ) ) in /Users/<user>/src/php-todo/app/vendor/php-di/php-di/src/Definition/Exception/InvalidDefinition.php:18 
Stack trace: #0 /Users/<user>/src/php-todo/app/vendor/php-di/php-di/src/Definition/Resolver/ObjectCreator.php(155): 
DI\Definition\Exception\InvalidDefinition::create(Object(DI\Definition\ObjectDefinition), 'Entry "ToDo\\Con...') #1 /Users/<user>/src/php-todo/app/vendor/php-di/php-di/src/Definition/Resolver/ObjectCreator.php(71): DI\Definition\Resolver\Objec in /Users/<user>/src/php-todo/app/vendor/php-di/php-di/src/Definition/Exception/InvalidDefinition.php on line 18

这似乎暗示我的呼吁addDefinitions没有以任何方式受到尊重。我已经尝试过DI\get,DI\autowireDI\create其他任何我能找到的东西......我没有额外的注册,我没有额外的任何有趣的东西。

的所有php-di文档都说(就像所有 DI 框架应该一样):“类型提示接口并注册要使用的具体类型”但是他们所有的 slim-bridge 示例都只是显示了一个正在注入的类(这要少得多有用的国际海事组织)。至此,如果我将 更改HelloController为接受 ctor 参数ListRepository而不是ListRepositoryInterface一切都按预期工作。

我只是不擅长 php 并且不懂接口和类型提示吗?我是一个糟糕的 php-di 吗?我在做一些 php 开发人员会认为是疯狂的事情吗?我是否只是误解了所有内容并通过 c# 有色眼镜看它?

4

2 回答 2

0

composer.json当我对部分进行更改"autoload": {"psr-4": { "App\\": "app" }}并忘记做时,自动加载有类似的问题composer dumpautoload

于 2020-11-10T10:11:14.493 回答
0

好的,这是一个带有自动加载的问题,非常特别是一个命名空间问题。我正在构建一个“todo”应用程序来学习一些特定于 php 的基础知识......所以我有一个ToDo. 我遵循 PSR-4 约定,但我在Todo.

大小写不匹配导致了一些意想不到的(对我来说)行为......考虑到 php 被解释等,这是有道理的,但我没有意识到类的实例化会有多懒惰。基本上我注册的完全限定名称与实际接口的声明不匹配

我可以使用ToDo\InterfaceThing,但Todo\InterfaceThing在文件中声明了src/InterfaceThing.php它,它不会爆炸......直到它尝试将这两种类型相互匹配并看到它ToDo并且Todo不一样。

本质上,在我预期的“类型未找到错误”(Repository::class 行)我最终注册了一个不存在的类型,它永远不会匹配,因为它不存在:)

于 2019-11-11T01:01:06.000 回答