Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cms Backend Laravel Package

typo3/cms-backend

The TYPO3 CMS backend package supplies the core administrative interface and framework: backend modules, user and group management, authentication, routing, layouts, and UI components for editors and administrators. It is a foundational system extension for extending TYPO3 backend functionality.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate the mental model: typo3/cms-backend is not a Laravel package. It is one system extension inside the TYPO3 Core monorepo (typo3/sysext/backend/) that happens to be published as a split Composer package. There is no service provider contract, no facades, no Eloquent. Dropping it into a composer.json of a Laravel app gets you files on disk and nothing else — it needs TYPO3\CMS\Core\Core\Bootstrap, a compiled Symfony DI container and the index.php entry point (SystemEnvironmentBuilder::run() → Bootstrap::init() → Core\Http\Application). Treat it as a place to learn and borrow architecture from, or as a dependency you will only encounter inside an actual TYPO3 project.

To actually run it:

composer create-project typo3/cms-base-distribution my-site
# or, inside an existing TYPO3 install
composer require typo3/cms-backend

Where to look first, in this order:

  1. typo3/sysext/backend/Configuration/Backend/Modules.php — the module registry. This is the closest thing to routes/web.php + a menu definition in one file.
  2. typo3/sysext/backend/Configuration/Backend/Routes.php and AjaxRoutes.php — backend routing, the analogue of web.php and api.php.
  3. typo3/sysext/backend/Configuration/RequestMiddlewares.php — the PSR-15 stack for the backend request type.
  4. typo3/sysext/backend/Classes/ — controllers, ModuleTemplateFactory, DocHeader buttons, toolbar items, backend user auth.
  5. typo3/sysext/backend/Classes/ServiceProvider.php — the failsafe container wiring (see Gotchas).

First use case — a backend module. This is the "hello world" equivalent and mirrors Route::get(...)->middleware('auth') plus a Blade view:

// Configuration/Backend/Modules.php
return [
    'web_myext' => [
        'parent' => 'web',
        'position' => ['before' => ['web_list']],
        'access' => 'user',
        'path' => '/module/web/myext',
        'controller' => \Vendor\MyExt\Controller\OverviewController::class,
        'labels' => 'myext.modules.overview',
        'icon' => 'EXT:myext/Resources/Public/Icons/module.svg',
    ],
];

…paired with a route in Configuration/Backend/Routes.php mapping the path to OverviewController::class . '::mainAction', a Fluid template under Resources/Private/Templates/, and a label in Resources/Private/Language/locallang_modules.xlf. Register the extension's own Configuration/Backend/Modules.php in ext_localconf.php? No — it is picked up automatically by the module registry.

Implementation Patterns

Backend routing. Routes.php and AjaxRoutes.php both return path => ['target' => 'Fqcn::method', 'access' => 'user']. Routes.php entries render full module pages; AjaxRoutes.php entries are JSON endpoints for widgets, tree loaders, autocomplete — the direct analogue of routes/api.php. Controllers receive the PSR-7 ServerRequestInterface and a Route object, or you resolve services through constructor injection.

Middleware. Configuration/RequestMiddlewares.php declares per-request-type stacks:

return [
    'backend' => [
        'myext/tenant-scope' => [
            'target' => \Vendor\MyExt\Middleware\TenantScope::class,
            'before' => ['typo3/backend/authentication'],
            'after'  => ['typo3/backend/locale'],
        ],
    ],
];

A MiddlewareInterface implementation is process(ServerRequestInterface $request, RequestHandlerInterface $handler) — same shape as Laravel's $next($request) closure, but handler-based. Ordering is resolved by Http\MiddlewareStackResolver from the before/after keys; there is no numeric priority.

Events over hooks. Old TYPO3 "hooks" ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']) are legacy. New extension points are PSR-14 events dispatched through Core\EventDispatcher. Register with the attribute on an autoconfigured listener class — this is exactly a Laravel listener:

#[AsEventListener]
public function __invoke(ModifyButtonBarEvent $event): void { /* … */ }

Alternatively tag the service event.listener in Services.yaml. When replacing a hook, ship both the event class and a Feature-*.rst changelog entry.

Dependency injection. Configuration/Services.yaml uses autowire: true, autoconfigure: true, public: false plus a resource: '../Classes/*' sweep, so constructor injection "just works" like Laravel's auto-resolution. Explicit entries are only needed for tags, factories and non-shared services. Extension points are consumed with !tagged_iterator (e.g. backend.toolbar for toolbar items) — the equivalent of Laravel's tagged() + TaggedIterator.

TCA instead of migrations. Records are configured in Configuration/TCA/<table>.php for own tables and Configuration/TCA/Overrides/<table>.php for foreign tables (pages, tt_content, be_users). New code should not touch $GLOBALS['TCA']; use Core\Schema\TcaSchemaFactory, which exposes typed TcaSchema/field/capability/relation objects — think typed casts/DTOs rather than array access. Core\DataHandling\DataHandler is still the single write path (versioning, workspaces, localization), so it is your "form request + transaction" layer.

Labels. Put English source strings in Resources/Private/Language/*.xlf and reference them with the translation-domain syntax introduced in v14.0: backend.modules.list, core.bookmarks:title, <f:translate key="myext.modules.overview" />. On 13.4 backports, use the legacy LLL:EXT:backend/Resources/Private/Language/locallang.xlf:identifier form instead.

Frontend assets. TypeScript/Sass sources live in Build/Sources/TypeScript/backend/ and Build/Sources/Sass/; compile via ./Build/Scripts/runTests.sh -s build. The compiled Resources/Public/{JavaScript,Css} is build output — never hand-edit it.

Testing. Everything is wrapped: CI=true ./Build/Scripts/runTests.sh -s unit, -s functional -d sqlite (default and fastest), -- --filter SomeTest. Unit tests extend TYPO3\TestingFramework\Core\Unit\UnitTestCase; functional tests extend ...\Core\Functional\FunctionalTestCase and get a real provisioned instance under typo3temp/var/tests/, resolving services with $this->get(SomeClass::class). Fixture extensions live in Tests/Functional/Fixtures/Extensions/, DB fixtures are CSV loaded with importCSVDataSet().

Gotchas and Tips

  • GPL-2.0, not MIT. This is the single biggest practical difference from the Laravel packages you normally pull in. Any distribution of a product that includes TYPO3 Core is a licensing decision; do not treat it as an MIT-style dependency in a commercial SaaS unless you have reviewed it.
  • Not installable into Laravel. The root composer.json maps PSR-4 namespaces and the code assumes the TYPO3 bootstrap, container and Environment. There is no Laravel service provider, no config/*.php publish step. Learn from the patterns; don't composer require it into an app.
  • The failsafe container. backend is one of five extensions (with core, install, fluid, dashboard) that provide Classes/ServiceProvider.php for the minimal container used by the install tool and broken-configuration states. Any class reachable from that path — including Fluid ViewHelpers used in install templates — that gains a required constructor argument must be wired manually there. Autowiring does not apply on this path.
  • Never edit build output. Resources/Public/JavaScript and Resources/Public/Css are generated. Change Build/Sources/ and rebuild. Also mind the naming shift: TypeScript folders use dashes (rte-ckeditor), sysexts use underscores (rte_ckeditor).
  • Exception codes are global. Every thrown exception needs a unique integer code — the Unix timestamp of when it was written, e.g. throw new SiteNotFoundException('…', 1521668882);. Never copy an existing code. ./Build/Scripts/runTests.sh -s listExceptionCodes reports duplicates and missing codes.
  • Two-part deprecations. A docblock (@deprecated since v<current>, will be removed in v<next>) and a trigger_error(..., E_USER_DEPRECATED) in the deprecated path, plus an RST changelog and extension-scanner entry. Never break API on a release branch.
  • Middleware ordering is declarative, not numeric. before/after are soft references resolved by MiddlewareStackResolver; ambiguous or cyclic constraints throw at container compile time — often on a cold cache, not on your machine.
  • Test fixtures don't resolve EXT:. importCSVDataSet() and pathsToProvideInTestInstance are plain file lookups. Use __DIR__-relative paths, not EXT:myext/....
  • Only use the wrapper. Do not call phpunit, phpstan, php-cs-fixer, npm or grunt directly — runTests.sh supplies the PHP version (-p), the DB service (-d sqlite|mysql|mariadb|postgres), chunking (-c 3/13) and bootstrap. When a suite fails in a way the code can't explain, -u refreshes the typo3/core-testing-* images first; -x forwards xdebug to port 9003.
  • The PHPStan baseline only shrinks. Do not add new ignores to Build/phpstan/phpstan-baseline.neon; regenerate it only after a PHPStan upgrade (-s phpstanGenerateBaseline).
  • XLIFF is checked in CI. Run -s checkIntegrityXliff; -s normalizeXliff fixes formatting. Edit only the English source files — translations are managed on Crowdin and are not in this repo.
  • Don't read $GLOBALS['TCA'] in new code. TcaSchemaFactory is the supported API; the global is kept for backwards compatibility only.
  • Borrowable patterns for your Laravel work: Modules.php → navigation + route groups in one declarative file; AjaxRoutes.php → routes/api.php; #[AsEventListener] → EventServiceProvider discovery; !tagged_iterator → container tags; TcaSchemaFactory → typed resource/cast layer over $GLOBALS-style arrays. These are the parts that translate cleanly back into day-to-day Laravel work; the rest is TYPO3-specific runtime you can't port.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
wandesnet/mercadopago-laravel
tsfcorp/email
larafony/core
laravel-enso/currencies
tartan/laravel-online-payment
gam/laravel-sat-catalogs
cloudcreativity/laravel-stripe
abdulelahragih/querybuilder
wedevbr/celcoin-laravel
surazdott/nepali-date
devsquad-cockpit/laravel
coding-socks/laravel-upload-handler
artisanbarista/laravel-shield
shopwwi/laravel-cache
instance-code/repository
flooris/prestashop-models
lab2view/laravel-generator
lenderspender/laravel-wizard
joecampo/laravel-notification-basecamp
square1/laravel-collection-rolling-average