SQL Resolver
SqlEntitySetResolver resolves OData queries against a SQL data source. It does not require an Eloquent model and is designed for ValueHelp scenarios, reporting views, and joined queries.
The resolver takes an EntitySetSourceInterface -- any object that provides a fresh Query\Builder via its query() method. This keeps the resolver decoupled from how the query is constructed.
Usage
Via SqlBinding (table or view name)
// In registerBindings():
$map->sql($container->getEntitySet('ValueHelp'), 'partner_value_help_view');
// With a specific connection:
$map->sql($container->getEntitySet('ReportData'), 'report_view', connection: 'reporting');Via SqlSourceBinding (dependency-injected source)
For sources that need implicit filters (tenant scoping, user permissions):
// In registerBindings():
$map->sqlSource($container->getEntitySet('FilteredPartners'), PartnerSource::class);Where PartnerSource implements EntitySetSourceInterface:
final readonly class PartnerSource implements EntitySetSourceInterface
{
public function __construct(private TenantContext $tenant) {}
public function query(): Builder
{
return DB::table('partners')->where('tenant_id', $this->tenant->id);
}
}Direct construction
use LaravelUi5\OData\Driver\Sql\SqlEntitySetResolver;
use LaravelUi5\OData\Service\Contracts\EntitySetSourceInterface;
$source = new class implements EntitySetSourceInterface {
public function query(): Builder
{
return DB::table('partners')
->join('addresses', 'partners.id', '=', 'addresses.partner_id')
->select('partners.id', 'partners.name', 'addresses.city');
}
};
$builder->bindEntitySet(
$container->getEntitySet('PartnerCities'),
new SqlEntitySetResolver($source),
);Constructor
new SqlEntitySetResolver(EntitySetSourceInterface $source)| Parameter | Type | Purpose |
|---|---|---|
$source | EntitySetSourceInterface | Provides a fresh Query\Builder via query() |
The source's query() method is called on each request to produce a fresh builder. OData system query options ($filter, $orderby, etc.) are applied on top.
Supported query options
| Option | Supported |
|---|---|
$filter | Yes -- via FilterToQuery visitor |
$search | Yes -- LIKE on string columns |
$select | Yes |
$orderby | Yes |
$top / $skip | Yes |
$count | Yes |
$compute | Yes |
$expand | No -- flat data, no relationships |
Interfaces implemented
EntitySetResolverInterface--resolve()yields rows,count()returns totalEntityResolverInterface--resolveOne()fetches a single row by key
How results are yielded
Uses cursor() for memory-efficient streaming. Each row is cast from stdClass to an associative array.
Typical use case: ValueHelp
A ValueHelp dialog in SAP UI5 needs a flat list of key/description pairs. Create a database view and expose it:
CREATE VIEW partner_value_help AS
SELECT p.id, p.name, a.city
FROM partners p
JOIN addresses a ON p.id = a.partner_id;// In registerBindings():
$map->sql($container->getEntitySet('PartnerValueHelp'), 'partner_value_help');The UI5 client can then query:
GET /odata/PartnerValueHelp?$filter=contains(name,'Acme')&$select=id,name,city&$top=20