PHP-D я не могу подключить интерфейс к реализации через тонкий мост - PullRequest
0 голосов
/ 11 ноября 2019

Я из мира контейнеров .net и DI / IOC, таких как autofac, ninject и т. Д.

Я ожидаю, и документация php-di предполагает, что должно работать следующее:

index.php / front controller

$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\autowire, DI\create и все остальное, что я могу найти ..... У меня нет дополнительных регистраций, у меня нет ничего НИЧЕГО интересного.

Вся документация php-di гласит (как и все DI-фреймворки должны ): «введите подсказку для интерфейса и зарегистрируйте конкретный тип для использования», но все их примеры тонкого-bridge просто показывает вводимый класс (что немного менее полезно для IMO). К этому моменту , если я изменю HelloController, чтобы принять параметр ctor ListRepository вместо ListRepositoryInterface, все работает как ожидалось.

Я простоплохо в php и я не понимаю интерфейсы и подсказки типа? Я плохой php-di? Я делаю что-то, что разработчики php сочли бы безумным? Я просто все неправильно истолковываю и смотрю на это через цветные очки c #?

1 Ответ

0 голосов
/ 11 ноября 2019

хорошо, это была проблема с автозагрузкой и ОЧЕНЬ конкретно с проблемой пространства имен. Я создаю приложение "todo", чтобы изучить некоторые php-специфические основы .... поэтому у меня есть корневое пространство имен ToDo. Я следую соглашениям PSR-4, НО я объявил интерфейс в пространстве имен Todo.

Несоответствие регистров вызывало некоторые неожиданные (для меня) поведения .... это имеет смысл, учитывая, что phpистолковано и т. д., но я не осознавал , насколько ленивым будет создание экземпляра класса. В основном, полное имя, которое я зарегистрировал, не совпадало с фактическим объявлением интерфейса

Я могу использовать ToDo\InterfaceThing, но иметь объявленный Todo\InterfaceThing в файле src/InterfaceThing.php, и он не взорвется .. .. пока он не попытается сопоставить два типа друг с другом и не увидит, что ToDo и Todo не совпадают.

По сути, там, где я ожидал "ошибку типа не найден" (строка Repository :: class), я в итоге зарегистрировал несуществующий тип, который никогда не будет сопоставлен, потому что он не существует:)

...