Skip to content

[HttpKernel] Provide a ForwardHelper as replacement for for AbstractController::forward #45336

Closed
@alexander-schranz

Description

@alexander-schranz

Description

Because of Composition over inheritance it would be nice to have a service providing the Forward functionality instead of have to duplicate that from the AbstractController if you con't want to use that controller.

The AbstractController could also use the ForwardHelper service.

Example Usage

class TestAction {
    public function __invoke(ForwardHelper $forwardHelper, Request $request): Response
    {
        return $this->forwardHelper->forward($request, OtherAction::class . '::testAction', ['id' => 5]);
    }
}

Example Implementation

A ForwardHelper could look like this:

<?php

namespace App\Common\Symfony\HttpKernel;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class ForwardHelper
{
    public function __construct(
        private HttpKernelInterface $httpKernel
    ) {
    }

    public function forward(
        Request $request,
        string $controller,
        array $path = [],
        array $query = []
    ): Response {
        $path['_controller'] = $controller;
        $subRequest = $request->duplicate($query, null, $path);

        return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
    }
}

Depending it it could also look like this when injecting the RequestStack:

<?php

namespace App\Common\Symfony\HttpKernel;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class ForwardHelper
{
    public function __construct(
        private HttpKernelInterface $httpKernel,
        private RequestStack $requestStack,
    ) {
    }

    public function forward(
        string $controller,
        array $path = [],
        array $query = []
    ): Response {
        $request = $this->requestStack->getCurrentRequest();
        $path['_controller'] = $controller;
        $subRequest = $request->duplicate($query, null, $path);

        return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
    }
}

Depending if we want if somebody could inject it's own Request object or not.

It could also be:

    public function forward(
        string $controller,
        array $path = [],
        array $query = [],
        ?Request $request = null,
    ): Response {}

What do you think about this?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions