Coming from Lodata
requires laravelui5/odataIf your Laravel app serves OData through flat3/lodata today, this page maps what you have onto laravelui5/odata. The protocol is the same, and so is the idea of turning Eloquent models into entity sets. What changes is the shape: a service class instead of a facade call, and an engine that only reads. Why this package exists at all is told in a post of its own.
1. Install and configure
composer require laravelui5/odata
php artisan vendor:publish --provider="LaravelUi5\OData\ODataServiceProvider"Most keys in config/odata.php carry the name you know from config/lodata.php:
config/lodata.php | config/odata.php | |
|---|---|---|
prefix | prefix | default odata, so clients keep their URL |
middleware | middleware | |
streaming | streaming | |
namespace | namespace | |
version | version | default 4.0 |
pagination.max, pagination.default | pagination.max, pagination.default | default page size 200 |
readonly | none | the engine is always read-only |
authorization | read_authorizer | a class instead of a gate, see §4 |
discovery.* | none | there is no discovery cache; the schema cache is odata:cache (Caching) |
| none | service_registry | which service answers a request, see §2 |
2. From discover() to a service class
In Lodata, models are discovered in a service provider:
// app/Providers/AppServiceProvider.php
public function boot(): void
{
\Lodata::discover(\App\Models\User::class);
}Here they are bound in a service class, in configure():
namespace App\OData;
use App\Models\User;
use LaravelUi5\OData\ODataService;
use LaravelUi5\OData\Service\Contracts\EdmBuilderInterface;
class AppService extends ODataService
{
public function serviceUri(): string
{
return '';
}
public function namespace(): string
{
return 'com.example.odata';
}
protected function configure(EdmBuilderInterface $builder): EdmBuilderInterface
{
$this->discoverModel(User::class);
return $builder->namespace($this->namespace());
}
}An empty serviceUri() puts the service at the root of the prefix, /odata/, where Lodata served its model. Entity sets are named the same way, as the plural of the model: User becomes Users.
Where Lodata used one of its own entity set drivers (a SQL query, a collection, a data source of your own), configure() takes a custom entity set:
$this->discoverCustomEntitySet(\App\OData\ActiveCustomers::class);How to write one, from a plain SQL view to a fully custom source, is on custom entity sets.
Finally, tell the package which service answers. The default registry serves an empty service, so a registry of your own is required, even for one service:
namespace App\OData;
use LaravelUi5\OData\Service\Contracts\ODataServiceInterface;
use LaravelUi5\OData\Service\Contracts\ODataServiceRegistryInterface;
class ServiceRegistry implements ODataServiceRegistryInterface
{
public function resolve(string $fullPath): ODataServiceInterface
{
return new AppService();
}
public function services(): array
{
return [new AppService()];
}
}// config/odata.php
'service_registry' => App\OData\ServiceRegistry::class,A registry that returns different services for different paths is how several services share one app; see multiple services.
3. Keeping fields out
Lodata leaves out a list of sensitive property names during discovery (discovery.blacklist). Here there is no list; you decide per model. Eloquent's $hidden and $visible decide: a column the model never serializes is neither declared in $metadata nor sent, as Lodata does too. For a cut that differs from the model's serialization, give the set an entity type of its own with only the columns you want. Both are on model discovery.
4. Authorization
Lodata asks a gate named lodata about every request once authorization is switched on. Here a read authorizer is bound in config/odata.php (read_authorizer). It sees the parsed query plan and records a verdict per entity set: allow, deny the request, or drop an $expand the actor may not see. The contract and an example are on read authorization.
5. Writes
With readonly switched off, Lodata creates, updates and deletes entities. laravelui5/odata does not: PUT, PATCH, DELETE and every POST outside $batch are refused. Writes stay in your application, in controllers or actions with their own validation. With LaravelUi5 Core, a write is a Ui5Action.
6. Functions
Lodata's operations become functions: declared on the builder in configure() and bound to a resolver in bindFunctions(). Actions, the writing kind of operation, are not supported. See functions and singletons.
7. What does not come across
$apply, the aggregation extension. A request with it is answered with501.- Asynchronous requests.
- An OpenAPI document.
- Connection files for Excel and Power BI. Both connect with the service URL instead; see Excel and Power BI.
8. Check it
Point your client at the new $metadata and compare it with Lodata's: entity set names, property types, keys. Then run the requests your client sends. The query options ($filter, $select, $expand, $orderby, $top, $skip, $count, $search, $compute) are each documented under Query Options.