Skip to content

Configuration ​

The LaravelUi5 configuration file can be published via

php
php artisan vendor:publish --tag=ui5-config

It defines the foundational settings for the LaravelUi5 platform: the UI5 version, the metadata and routes exposed to app manifests, the registry and context-factory implementations, the middleware stacks on the two route groups, the auth switch, the artifact-resolver chain, and the modules your host loads.

Every key below appears in the published file with its own comment block; this page is the same material with the reasoning spelled out.

The following sections provide a structured breakdown of each configuration key, its purpose, and how it influences the system’s behavior.

OpenUI5 Framework Version ​

Key version

The OpenUI5 version an app loads from the CDN in built mode — unless the app names its own:

  • An app's own version wins. ui5:app reads framework.version from the source project's ui5.yaml and writes it into the app's base class (getUi5Version()); --refresh keeps it current. That happens for framework.name: OpenUI5 only — the bootstrap loads from the OpenUI5 CDN — and an app whose ui5.yaml names no version returns null and uses this key.
  • Scaffolding. ui5:assemble writes this value as the generated app's minUI5Version.
  • Workspace mode is unaffected: the UI5 dev server serves the framework.

Must be a valid version tag from the official UI5 CDN (e.g., "1.120.5").

changed in 3.0The per-app version is new; until 3.0 this key was the only one, and nothing read it while scaffolding.

Manifest Metadata ​

Key meta

Optional key/value pairs merged into the laravel.ui5.meta block of every generated manifest.json, alongside the default 'generator' => 'LaravelUi5 Core' — which always wins on a key conflict.

php
'meta' => [
    'build'       => env('APP_BUILD'),
    'environment' => app()->environment(),
],

Leave it empty unless you need to stamp build or environment facts into your manifests. It is a flat map, read once per manifest build.

UI5 App Routing ​

Key routes

Allows you to define Laravel route names that will be exposed to the UI5 application's manifest.json. Useful for authentication routes or navigation purposes.

The entries are automatically resolved via Laravel's route(...) helper and injected into the laravel.ui5.routes section of the generated manifest.

Rules

  • Values must be valid Laravel route names.

  • URLs may be relative or absolute depending on routing config.

  • Example provided in comments:

    php
    'routes' => [
        'login'   => 'user.login',
        'logout'  => 'user.logout',
        'profile' => 'user.profile',
        'home'    => 'dashboard.index',
    ]

UI5 Registry Implementation ​

Key registry

Value \LaravelUi5\Core\Ui5\Ui5Registry::class

This option controls which implementation of the Ui5RegistryInterface is used by the LaravelUi5 system.

Ui5Registry is the in-memory default: it boots by reflecting every registered module and artifact on each request. That is the right trade for development — a code change is visible immediately, with nothing to invalidate.

To swap it, point this key at another Ui5RegistryInterface implementation. That is the seam the SDK uses: its SdkRegistry layers database-backed state on top of the same two-pass boot, and pairs with a cached registry that reads a warm snapshot instead of reflecting. Registry selection is a single class-string here — there is no second key to set.

Registered UI5 Modules ​

Key modules

A flat list of module classes — each implementing Ui5ModuleInterface — that this host loads. A module is a cohesive functional unit: a UI5 application or library, plus its artifacts (cards, charts, reports, tiles, actions).

php
'modules' => [
    \Showcase\ShowcaseModule::class,
],

Only the class matters; the registry keys each module by the namespace it declares, and artifacts are routed by their own namespace and version (ui5/app/com/example/[email protected]/index.html), never by a key in this array.

Infrastructure modules do not belong here. Modules contributed by installed packages — Core's own CoreModule, and whatever your packages register — are collected automatically at boot and merged ahead of this list. Listing them again is redundant at best.

What this array is, is a product decision: only modules named here are visible and supported. That is why the step stays manual even though the package could technically register itself — see Register the app with your host.

Per-Request Context ​

Key context_factory

Value \LaravelUi5\Core\Runtime\CoreContextFactory::class

The implementation of Ui5ContextFactoryInterface that builds the per-request Ui5ContextInterface (Core's own is Ui5CoreContext). Core's factory resolves two things — the addressed artifact and the request locale — because that is all a stateless Core knows.

Swap it to enrich the context. This is the seam the SDK uses: its factory adds tenant, actor and principal, which is what lets an SDK provider method-inject a context that can answer who is asking.

A context of your own implements the whole interface — artifact(), locale() and slot(). changed in 3.0slot() is new on the interface; see Reading a slot anywhere for the one-liner.

Route Middleware ​

Key middleware

The stack applied to the ui5/* route group — app entry points, manifests, cards, dashboards, reports, resources, actions and assets:

php
'middleware' => [
    'web',
    \LaravelUi5\Core\Http\Middleware\ResolveRequestLanguage::class,
    \LaravelUi5\Core\Http\Middleware\ResolveUi5Context::class,
    \LaravelUi5\Core\Http\Middleware\EnsureUi5Authenticated::class,
],

ResolveRequestLanguage sets the request's language from sap-language, else Accept-Language — the language part only, so de-AT becomes de — and with it app()->getLocale(). It runs before the context is built, which carries the language. ResolveUi5Context binds the per-request context into the container — every artifact resolution downstream depends on it, so it must come before anything that reads it. EnsureUi5Authenticated is the opt-in turnstile described under auth_enabled.

Append your own middleware; think hard before removing either of these.

OData Route Middleware ​

Key odata_middleware

The stack applied to the odata/* route group:

php
'odata_middleware' => [
    'web',
    \LaravelUi5\Core\Http\Middleware\ResolveRequestLanguage::class,
    \LaravelUi5\Core\Http\Middleware\FetchCsrfToken::class,
    \LaravelUi5\Core\Http\Middleware\ResolveODataEndpoint::class,
    \LaravelUi5\Core\Http\Middleware\EnsureODataAuthenticated::class,
],

Each entry earns its place:

MiddlewareWhy it is there
ResolveRequestLanguagesets the request's language from the client — see below
FetchCsrfTokenimplements the SAP Fiori X-CSRF-Token: Fetch handshake
ResolveODataEndpointparses {namespace}@{version}, binds the resolved ODataServiceInterface; an unknown namespace is a 404, an artifact without OData a 400 — both as an OData error envelope with OData-Version: 4.0
EnsureODataAuthenticatedanswers an honest 401 with an OData error envelope

⚠️ Do not replace the OData auth middleware with Laravel's stock auth. The default guest response is a 302 → /login, and the UI5 v4 model's fetch follows it transparently, parses the login HTML, finds no OData-Version header and throws a protocol error that has nothing to do with the real problem. EnsureODataAuthenticated exists to make an auth failure look like an auth failure.

The request language ​

since 3.0 ResolveRequestLanguage reads the language the UI5 client asks for and sets it on the request and on the app, so $context->locale(), __() and anything that reads app()->getLocale() agree for the rest of the request:
  1. the sap-language query parameter, if the app wrote one into its service URL;
  2. else the first entry of Accept-Language — which OpenUI5 sends on every OData request, code-list loads included, taken from sap-ui-language;
  3. else nothing: the app's configured locale stays.

The value is a language, not a locale — the primary subtag, lower case: de-AT and DE both become de. Laravel's translator does not fall back from de_AT to de, and texts are kept per language. A value that is not a language tag (SAP's internal codes such as 1Q) is ignored and the next channel decides.

Keep it first after web, ahead of anything that builds the context — on an SDK host, ahead of BindSdkContextForOData.

⚠️ A published config is not updated by composer update. A host that published config/ui5.php before 3.0 adds the line by hand; without it, OData responses ignore the client's language.

The locale slot is a separate value and is not touched: it is read through the slot pipeline, from the query string or its default.

Authentication Enforcement ​

Key auth_enabled

Default env('ENABLE_AUTH_4_UI5', true)

The master switch for both auth middlewares. Set it false and the gate is inert — every request passes, which is convenient locally and wrong in production.

It is worth being precise about what this does and does not control. Core owns no identity: no user model, no credential check, no session, no login page. The middleware ensures a result someone else produced. Everything it reads is host-supplied:

Core readsOwned by
Auth::check()your configured guard
route('login')your route
config('ui5.auth_enabled')this key
$module->requiresAuth()the artifact's own module

So the gate is opt-in twice over: with no login route, or with this key false, it is a no-op.

Artifact Resolvers ​

Key artifact_resolvers

Value [\LaravelUi5\Core\Runtime\PathBasedArtifactResolver::class]

An ordered chain mapping an incoming request path to a registered artifact. The default resolver covers the {namespace}@{version} convention every ui5:* generator produces, which is all a Core-only host needs.

Hosts and packages append to the chain to serve additional URL schemes — the SDK adds a resolver for shell-context requests, for instance. Order matters: the first resolver that returns an artifact wins.

OData Configuration ​

The OData engine has its own config file, published separately by laravelui5/odata — none of its keys live in config/ui5.php. See the laravelui5/odata documentation.

One key there is Core's, though: Core's service provider forces odata.register_routes = false at registration time, so it can install the OData routes itself with the odata_middleware stack above. Do not set it back to true — you would get double-registered routes, and the second set would have no auth and no CSRF handling.