Skip to content

Configuration Reference ​

Every setting lives in config/odata.php, published with:

bash
php artisan vendor:publish --provider="LaravelUi5\OData\ODataServiceProvider"

Each key is optional — the engine falls back to the same defaults if the file is absent.

KeyDefaultSets
prefix'odata'The URL prefix for all routes
register_routestrueWhether the package registers routes at all
middleware[]Middleware on the package's routes
streamingtrueStream responses or buffer them
namespace'io.pragmatiqu'Fallback CSDL namespace
version'4.0'Protocol version advertised in $metadata
service_registryODataServiceRegistry::classHow a URL finds its service
read_authorizerAllowAllReadAuthorizer::classPer-actor read gating
pagination.default200Page size when the client asks for none
pagination.maxnullCeiling the client cannot exceed

prefix ​

php
'prefix' => env('ODATA_PREFIX', 'odata'),

The URL segment every OData route hangs off, so the service root becomes https://example.test/odata. Trailing slashes are trimmed.

Ignored when register_routes is false — the host's own route group owns the prefix in that case.

register_routes ​

php
'register_routes' => true,

Whether the package registers its own route group during boot.

Set it to false when the host application wants to mount the engine itself — it then includes the package's route file inside its own group, with its own prefix and middleware:

php
// In the host's ServiceProvider::boot()
Route::prefix('odata')
    ->middleware(config('my-app.odata_middleware'))
    ->group(base_path('vendor/laravelui5/odata/routes/odata.php'));

This is how LaravelUi5 Core mounts OData, and it is the right switch whenever OData routes need to sit behind the same middleware stack as the rest of the application. See Multi-Service.

middleware ​

php
'middleware' => [],

Middleware applied to the routes this package registers. Authentication, CORS, rate limiting, tenancy resolution — whatever the reads need.

php
'middleware' => ['auth:sanctum', 'throttle:api'],

Ignored when register_routes is false, since the host's route group then supplies its own stack.

Middleware gates the request; it sees a URL, not a parsed query. To gate individual entity sets — including sets reached through $expand — use Read Authorization.

streaming ​

php
'streaming' => true,

When true, collection responses stream row by row: the engine echoes JSON as the resolver yields, so a large result set never materialises in memory. This is the behaviour the engine is built for.

The cost is that headers are already sent when the first row goes out, so an error raised mid-stream cannot change the status code. The stream stops where it is and the error JSON is appended, introduced by OData-error: — see Streaming error handling, which also documents the known flaw in that mechanism: the response announces an HTTP trailer it does not actually send, and the appended marker leaves the body as invalid JSON.

Set it to false to buffer the whole response before sending. Errors then produce an ordinary error response with the correct status, at the cost of holding the result set in memory. That is the way around the flaw above, and it is also useful while debugging or behind a proxy that mishandles trailers.

namespace ​

php
'namespace' => env('ODATA_NAMESPACE', 'io.pragmatiqu'),

The CSDL namespace used when a service does not declare its own. Most services do — a service class overriding namespace() ignores this key entirely — so it matters mainly for the default single-service setup.

xml
<Schema Namespace="io.pragmatiqu" xmlns="http://docs.oasis-open.org/odata/ns/edm">

The default is the same whether or not config/odata.php was published — there is one default value in the package, and it is the one printed above. Set something that identifies your domain: the namespace is part of every fully qualified type name a client sees, so changing it on a service that is already in use is a breaking change for its clients.

plannedThe in-code fallback still says something else; the two are being brought together.

version ​

php
'version' => env('ODATA_VERSION', '4.0'),

The protocol version advertised in $metadata and in the OData-Version response header — one value, both surfaces. '4.0' is the default: the engine is built against the v4.01 specification texts but does not advertise 4.01 unless you say so.

plannedToday the value reaches `$metadata` only; every handler writes the header literally.

service_registry ​

php
'service_registry' => LaravelUi5\OData\ODataServiceRegistry::class,

The ODataServiceRegistryInterface implementation that maps an incoming path to an ODataService.

The shipped default serves one service for the whole OData URL space. Point the key at your own implementation to route different paths to different services — per module, per tenant, per API version:

php
'service_registry' => App\OData\ServiceRegistry::class,

See Multi-Service. A service can also bypass the registry entirely and be mounted on its own route — see Route-composed services.

read_authorizer ​

php
'read_authorizer' => LaravelUi5\OData\Service\AllowAllReadAuthorizer::class,

The ReadAuthorizerInterface consulted before every read. The shipped default records no verdict, so an unconfigured service serves whatever its schema declares to whoever reaches the URL.

php
'read_authorizer' => App\OData\GateReads::class,

The seam has its own page — see Read Authorization for the contract, the three verdicts, the message format, and what it deliberately does not cover.

pagination ​

php
'pagination' => [
    'max'     => null,
    'default' => 200,
],

Server-driven paging. default is the page size applied when the client expresses no preference; max is the ceiling a client cannot exceed. Both accept null — default: null means no page size is imposed, max: null means no ceiling.

The effective page size is resolved in three steps:

  1. Read Prefer: odata.maxpagesize=N from the request, if present.
  2. If the client sent no preference, apply default.
  3. Clamp the result to max, if one is set.

A page size only takes effect when the request carries no explicit $top — a client asking for a specific window gets that window. When paging does apply, the response echoes Preference-Applied: odata.maxpagesize=N and carries an @odata.nextLink.

php
'pagination' => [
    'max'     => 1000,   // nobody gets more than 1000 rows in one response
    'default' => 200,
],

Leaving default at null and max at null means an unbounded collection is served in full. See Pagination — including the current caveat about what the next link does and does not carry.

Environment variables ​

Three keys read the environment, so they can differ per deployment without editing the file:

VariableConfig KeyDefault
ODATA_PREFIXodata.prefix'odata'
ODATA_NAMESPACEodata.namespace'io.pragmatiqu'
ODATA_VERSIONodata.version'4.0'