Search by

konradmichalik / typo3-routing

konradmichalik

Attribute Routing - Register frontend endpoints via PHP attributes on controller methods, as an attribute-based alternative to the missing frontend counterpart of AjaxRoutes.php.

Package info

github.com/konradmichalik/typo3-routing

Type:typo3-cms-extension

pkg:composer/konradmichalik/typo3-routing

Statistics

Installs: 5 930

Dependents: 1

Suggesters: 0

Stars: 6

Open Issues: 6

1.5.0 2026-11-05 14:22 UTC

README

Extension icon

TYPO3 extension typo3_routing

Latest Stable Version TYPO3 Supported PHP Versions CGL Coverage Tests License

This extension lets you register frontend endpoints via PHP attributes on controller methods — the path, its typed arguments and its caching, rate limiting, authentication and CORS policy all declared where the endpoint lives. It is response-format agnostic: return JSON, HTML, XML, or a download.

The frontend has no equivalent to the backend-only Configuration/Backend/AjaxRoutes.php; closing that gap is where this extension started, though a #[Route] today carries considerably more than a path-to-controller mapping.

Note

The goal is a familiar, Symfony-Routing-like developer experience: declare a frontend endpoint with a single #[Route] attribute instead of wiring a custom middleware and duplicating the path across PHP and JavaScript.

✨ Features

  • Attribute routing: declare an endpoint with #[Route] on a controller method, grouped by a class-level prefix if needed
  • Typed arguments: methods receive type-cast path, query and body values, with optional value constraints
  • URL generation: a Fluid ViewHelper and a PHP generator, so a path lives in one place
  • Opt-in route features: caching, rate limiting, authentication with CSRF protection, and CORS, each as its own attribute
  • Tooling: routing:debug lists and audits every route, routing:openapi exports an OpenAPI 3.1 document

🔥 Installation

Requirements

  • TYPO3 >= 13.4
  • PHP 8.2+

Composer

Packagist Packagist Downloads

composer require konradmichalik/typo3-routing

TER

TER version TER downloads

Download the zip file from TYPO3 extension repository (TER).

🚀 Quick start

Implement RouteControllerInterface, register the controller as a service, and annotate a public method with #[Route]:

use KonradMichalik\Typo3Routing\Attribute\Route;
use KonradMichalik\Typo3Routing\Routing\RouteControllerInterface;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Http\JsonResponse;

final readonly class CourseSearchController implements RouteControllerInterface
{
    #[Route(path: '/api/course-search/count', name: 'course_search_count')]
    public function count(): ResponseInterface
    {
        return new JsonResponse(['count' => 42]);
    }
}

That's it: GET /api/course-search/count now returns your JSON.

Everything else is opt-in on top of that. A route can take typed arguments, validate input, cache its response, and throttle clients, all declared with attributes, while the controller stays plain:

use Symfony\Component\Routing\Requirement\Requirement;

#[Route(path: '/api/courses/{id}', name: 'course_show', requirements: ['id' => Requirement::DIGITS])]
#[Cache(lifetime: 3600, tags: ['tx_courses_domain_model_course'])]
#[RateLimit(limit: 60, interval: '1 minute')]
public function show(int $id, int $page = 1): ResponseInterface
{
    // $id  ← path placeholder, cast to int (404 if not digits)
    // $page ← ?page=… query param, defaults to 1
    return new JsonResponse(/* … */);
}

See The #[Route] attribute for the full reference and Typed controller arguments for how the signature is fed.

📚 Documentation

Full documentation lives in docs/, grouped into four parts. The performance figures have a row of their own:

Part What's inside
Defining routes The #[Route] attribute, route groups, typed controller arguments, and URL generation — the only part you need to ship an endpoint
Route features The opt-in attributes: #[Authenticate], #[Cache], #[RateLimit], #[Cors], and how they interact
Operating it Every extension setting, the routing:debug, routing:match and routing:lint commands, and the OpenAPI export
Background How it compares to the alternatives, how it works underneath, measured performance, and the @api surface for tooling
Performance About 0.63 ms per matched request compared to a hand-written middleware, about 0.19 ms on an ordinary page request, and how to reproduce both

Tip

Want to expose these routes to AI agents/MCP clients? typo3-routing-mcp adds a #[McpTool] attribute next to an existing #[Route] and serves it over Streamable HTTP.

🧑‍💻 Contributing

Please have a look at CONTRIBUTING.md.

⭐ License

This project is licensed under GNU General Public License 2.0 (or later).