Проблема с тонким контроллером: должен быть экземпляр ContainerInterface, задан экземпляр Slim\\Container

Я пытаюсь использовать контроллер в Slim, но продолжаю получать сообщение об ошибке

Перехватываемая фатальная ошибка PHP: аргумент 1, переданный в
TopPageController::__construct(), должен быть экземпляром ContainerInterface,
передан экземпляром Slim\Container

Мой index.php

<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

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

spl_autoload_register(function ($classname) {
    require ("../classes/" . $classname . ".php");
});

$app = new \Slim\App(["settings" => $config]);
$app->get('/', function (Request $request, Response $response) {
    $response->getBody()->write("Welcome");
    return $response;
});
$app->get('/method1', '\TopPageController:method1');
$app->run();
?>

Мой TopPageController.php

<?php
class TopPageController {
   protected $ci;
   //Constructor
   public function __construct(ContainerInterface $ci) {
       $this->ci = $ci;
   }

   public function method1($request, $response, $args) {
        //your code
        //to access items in the container... $this->ci->get('');
        $response->getBody()->write("Welcome1");
        return $response;
   }

   public function method2($request, $response, $args) {
        //your code
        //to access items in the container... $this->ci->get('');
        $response->getBody()->write("Welcome2");
        return $response;
   }

   public function method3($request, $response, $args) {
        //your code
        //to access items in the container... $this->ci->get('');
        $response->getBody()->write("Welcome3");
        return $response;
   }
}
?>

Спасибо. Я использую Слим 3.


person lost111in    schedule 19.06.2016    source источник
comment
У вас нет подходящего пространства имен в вашем ContainerInterface. Должно быть Interop\Container\ContainerIterface   -  person geggleto    schedule 19.06.2016


Ответы (4)


Похоже, ваш код основан на документации Slim 3 по адресу http://www.slimframework.com/docs/objects/router.html, который не содержит всего необходимого кода, чтобы избежать возникновения исключения.

По сути, у вас есть два варианта заставить его работать.

Вариант 1:

Импортируйте пространство имен в свой index.php так же, как это делается для Request и Response:

use \Interop\Container\ContainerInterface as ContainerInterface;

Вариант 2:

Измените конструктор TopPageController на:

public function __construct(Interop\Container\ContainerInterface $ci) {
    $this->ci = $ci;
}

TL;DR

Причина, по которой возникает исключение, заключается в том, что класс Slim\Container использует интерфейс Interop\Container\ContainerInterface (см. исходный код):

use Interop\Container\ContainerInterface;

Поскольку Slim\Container расширяет Pimple\Container, следующие объявления должны быть действительными (рабочими) типами для метода вашего контроллера:

public function __construct(Pimple\Container $ci) {
    $this->ci = $ci;
}

...или даже...

public function __construct(ArrayAccess $ci) {
    $this->ci = $ci;
}
person Werner    schedule 08.07.2016
comment
Если это было результатом обновления Slim, ответ от Trendfischer лучше всего. Interop\Container устарел, а Slim изменен на Psr\Container. Лучше обновить свой код, чтобы он соответствовал обновлению от Slim. - person LStarky; 19.06.2020

На основе более позднего изменения в Slim3 (с версии 3.12.2 на 3.12.3) требуется немного другой ContainerInterface. Это изменяет \Interop\ на \Psr\. Добавьте следующее поверх вашего кода или измените существующий use:

use Psr\Container\ContainerInterface;

Или изменить конструктор:

public function __construct(\Psr\Container\ContainerInterface $container)
{
    $this->container = $container;
}
person Trendfischer    schedule 29.11.2019
comment
Проблема возникла у меня при обновлении с версии 3.12.2 => 3.12.3 - person Dariusz Chowański; 11.12.2019
comment
@DariuszChowański Спасибо, забыл упомянуть. Я полагаю, что они сделали эту версию патча, когда модуль Interop получил статус устаревшего. Я добавил информацию о версии в ответ. - person Trendfischer; 12.12.2019

Просто вставьте приведенный ниже код в свой контроллер.

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use \Interop\Container\ContainerInterface as ContainerInterface;

Конструкция вашего контроллера должна выглядеть так, как показано ниже.

public function __construct(ContainerInterface $container) {
    parent::__construct($container);
}

Я думаю, вы делаете ошибку, указывая пространство имен в контроллере для ContainerInterface.

person Community    schedule 29.05.2017

Поскольку container-interop/container-interop устарел, просто замените его на psr/container (Psr\Container\ContainerInterface).

person Hariom Maurya    schedule 17.12.2020