Align Extbase more with Symfony

Since TYPO3 uses a lot of the components of Symfony already, it would be great if Extbase would also be similar to Symfony.

Symfony has 2 great features which are currently missing in Extbase:

  1. Allow to specify allowed methods for an action (GET, POST, PUT…)
  2. Set permissions which user is allowed to call actions

Surprisingly the backend is already feature number one where you can define allowed methods in typo3/sysext/backend/Configuration/Backend/Routes.php for example like so:

'login_request_token' => [
    'path' => '/login/request-token',
    'access' => 'public',
    'methods' => ['POST'],
    'target' => Controller\LoginController::class . '::requestTokenAction',
],

Because the routing works completely different in Extbase, it is time to rethink it.

My proposal is to also use Annotations like in Symfony also in Extbase like so:

class BackendUserController extends ActionController
{
    #[Route(path: '/removeFromCompareList/{uid}/{redirectToCompare}', name: 'removeFromCompareList', methods: ['POST'])]
    #[IsGranted('customer')]
    public function removeFromCompareListAction(int $uid, int $redirectToCompare = 0): ResponseInterface
    {
        $this->removeFromCompareList('compareUserList', $uid);
        if ($redirectToCompare) {
            return $this->redirect('compare');
        }
        return $this->redirect('index');
    }
}

What are your thoughts about it?

Would this be something that could be implemented for TYPO3 13?

I only thought about routing so far:

I think it does not work like that within TYPO3. Routing is controlled by the integrator, not by the extension developer.
This is a common “over-simplification” of Extbase, in my opinion. It is easy to forget that Extbase is not an application framework in the typical sense (i.e. like Symfony, Laravel, RoR, etc.). An Extbase extension does not compose the full system, whereas a Laravel project is a full system.
That way, a lot of common concepts in these full application frameworks are not applicable to Extbase (or even TYPO3).

Thank you for your quick reply. Concerning the routing, THIS is possible already and I’m very happy with this solution:

https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Routing/AdvancedRoutingConfiguration.html#extbase-plugin-enhancer

Nothing more to add here. The only thing that is missing is the limitation to POST request for some methods.

Would there be the need to couple routes to a specific extension and/or plugin inside route definitions, then? Is it enough to know FQCN and method of the controller to invoke?

No, the route annotation does nothing new. It would do exactly the same like the extbase plugin route enhancer but instead of the yaml in PHP.

routeEnhancers:
  NewsPlugin:
    type: Extbase
    limitToPages: [13]
    extension: News
    plugin: Pi1
    routes:
      - routePath: '/list/'       // <- this would be in PHP
        _controller: 'News::list' // <- this would be in PHP
        methods: // something like this would be equal with the annotation
        -  POST

Maybe I’m missing your point, but my point is that it’s not about the syntax of the route definition, but the question “who?” defines it.
If it is coupled in PHP as annotation with the controller, then the who is the extension’s author.
If it is using the current means (yaml with the various enhancers), then the who is the integrator (aka user of the extension) defines the route.

That’s what makes the major difference to me. I wouldn’t use an extension, where the author dictates the route names.

This whole topic is NOT about routing but about permissions!

I’m just looking for good solutions how a possible implementation could look like that would enable an integrator to define which kind of methods can only be called by certain HTTP methods and only be executed with permissions that the logged in frontend user has.

That means: You should only be allowed to persist an object with a POST/PATCH/PUT request and not with a GET request. Currently the HTTP method doesn’t matter and that fact is my issue that I’m trying to solve in a nice way that works for everyone.

@liayn Why would it be a problem for you if an extension author defines that certain actions can only be called with a POST request?

Nothing against that. But I was under the impression you are talking about routing in general, which involves the “path”. That’s the part, that bothered me.

I really like the idea. I’ve just opened an issue that could built upon the proposal: https://forge.typo3.org/issues/102567

And I’m also thinking this should be made by the developer, not integrator. The extension defines features and actions. It therefore is also in charge to define the expected behaviour. The integrator needs to integrate that into the system. But he should not be able to alter this part.

This is my current solution as a workaround in a controller:

public function processRequest(RequestInterface $request): ResponseInterface
{
    if ($request->getMethod() === 'GET' && $request->getControllerActionName() === 'delete') {
        $content = GeneralUtility::makeInstance(ErrorPageController::class)->errorAction(
            'Method not allowed',
            'GET method not allowed for this action!',
            AbstractMessage::ERROR,
            0,
            405
        );
        throw new PropagateResponseException(new HtmlResponse($content, 405));
    }

    return parent::processRequest($request);
}