Как использовать Symfony HttpFoundation с PHP-DI для MVC

Я изо всех сил пытаюсь создать рабочую структуру MVC для проекта.

Что я использую:

Вот мой код.

container.php

$containerBuilder = new \DI\ContainerBuilder();
$containerBuilder->useAutowiring(true);
$containerBuilder->useAnnotations(true);
$containerBuilder->addDefinitions(__DIR__ . '/container-config.php');
$container = $containerBuilder->build();

контейнер-config.php

use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Psr\Container\ContainerInterface;

return [

    'request' => function() {
        return Symfony\Component\HttpFoundation\Request::createFromGlobals();
    },

    'session' => function() {
        return new Symfony\Component\HttpFoundation \Session\Session();
    }

    Environment::class => function () {

        $loader = new FilesystemLoader(__DIR__ . '/../templates');
        $twig = new Environment($loader, [
            'cache' => __DIR__ . '/../var/cache/templates',
        ]);

        return $twig;
    },
];

router.php

use Pecee\SimpleRouter\SimpleRouter as R;
use Pecee\Http\Middleware\BaseCsrfVerifier;
use App\App;

R::csrfVerifier(new BaseCsrfVerifier());
R::setDefaultNamespace('\App\Controller');
R::enableDependencyInjection($container);

R::get('/', 'ProductController@index', ['as' => 'products']);

R::start();

Вот мой базовый контроллер

namespace App;

use Symfony\Component\HttpFoundation\Request;
use Twig\Environment;

class BaseController
{

    protected $request;

    protected $twig;

    public function __construct(Request $request, Environment $twig)
    {

        $this->request = $request;

        $this->twig = $twig;

    }

}

Наконец-то мой контроллер продукта

namespace App\Controller;

use App\BaseController;

class ProductController extends BaseController
{

    public function index()
    {

        dump($this->request); // returns the request object
        dump($this->request->query->all()); // return empty array

    }

}

Первая проблема заключается в том, что объект запроса, который я установил в контейнере, не работает внутри моего контроллера.

Пример URL example.com?foo=bar

dump($this->request)

Эта строка возвращает Symfony\Component\HttpFoundation\Request, как и должно быть, но она кажется новой, потому что я не могу получить параметры запроса с $this->request->query->all(), она возвращает пустую.

Если я создам Symfony\Component\HttpFoundation\Request::createFromGlobals(); как глобальную переменную, она будет работать, как и ожидалось, и сброс $this->request->query->all() вернет ожидаемый массив.

Итак, мой вопрос: как мне лучше всего соединить все эти компоненты вместе, чтобы иметь работающую структуру?

Благодарю вас!


person C. Ovidiu    schedule 14.07.2020    source источник
comment
Вы можете попробовать изменить 'request' =› function() { на Request::class =› function() {, как это сделано для сервиса Twig. Я не знаком с PHP-DI, но кажется разумным, что для работы autowire ему нужно имя класса в качестве идентификатора службы.   -  person Cerad    schedule 14.07.2020


Ответы (1)


Ничто в PHP-DI не предполагает, что внедрение зависимостей происходит в соответствии с именами параметров, но вместо этого имеет значение класс. PHP-DI волшебным образом внедряет любой класс, если он (еще) не определено. (AnnotationBasedAutowiring будет создать класс из ничего, если нет определения предоставляется)

Однако на самом деле использование аннотаций для запуска инъекций выглядит совсем иначе, и ИМХО, по-видимому, не так. то, что вы хотите, или вы бы сделали это.

Поскольку ваши определения содержат только запись для request, но не для Symfony\Component\HttpFoundation\Request, контейнер с радостью создаст ее для вас.

Чтобы исправить это, вы должны установить другой ключ, который соответствует:

use Symfony\Component\HttpFoundation\Request; // <-- added

return [
    Request::class => function() {
        return Request::createFromGlobals();
    },
    // ...
];
person Jakumi    schedule 14.07.2020
comment
Почти уверен, что вы неправильно понимаете документы в отношении вызываемых объектов. Я сам не пробовал, но, как и любое другое определение, фабрики вызываются один раз, и каждый раз, когда фабрику необходимо разрешить, возвращается один и тот же результат. подразумевает, что сгенерированный объект $request будет совместно использоваться везде, где он будет внедрен. В противном случае особого смысла нет. - person Cerad; 14.07.2020
comment
@Cerad, ты абсолютно прав. адаптировали мой ответ. также, только теперь я действительно понял ваш первоначальный комментарий под вопросом ;o/ - person Jakumi; 14.07.2020