Recipe: SAP UI5 ValueHelp
This recipe shows how to create a ValueHelp entity set -- a flat list of key/description pairs sourced from a custom SQL query.
1. Create the custom entity set
Implement CustomEntitySetInterface to colocate the entity type definition, SQL query, and resolver logic in a single class:
php
use Illuminate\Support\Facades\DB;
use LaravelUi5\OData\Edm\Contracts\Container\PrimitiveTypeEnum;
use LaravelUi5\OData\Edm\Contracts\Type\EntityTypeInterface;
use LaravelUi5\OData\Edm\Property\Property;
use LaravelUi5\OData\Edm\Type\EntityType;
use LaravelUi5\OData\Edm\Type\PrimitiveType;
use LaravelUi5\OData\Protocol\Planning\EntitySetQueryPlan;
use LaravelUi5\OData\Service\Contracts\CustomEntitySetInterface;
use LaravelUi5\OData\Service\Contracts\QueryPlanInterface;
final class PartnerValueHelp implements CustomEntitySetInterface
{
public function entitySetName(): string
{
return 'PartnerValueHelp';
}
public function entityType(string $namespace): EntityTypeInterface
{
$int64 = new PrimitiveType(PrimitiveTypeEnum::Int64);
$string = new PrimitiveType(PrimitiveTypeEnum::String);
$keyProp = new Property('id', $int64);
return new EntityType(
namespace: $namespace,
name: 'PartnerValueHelp',
key: [$keyProp],
declaredProperties: [
$keyProp,
new Property('name', $string),
new Property('city', $string),
new Property('country', $string),
],
);
}
private const SQL = <<<'SQL'
SELECT p.id, p.name, a.city, a.country
FROM partners p
JOIN addresses a ON p.id = a.partner_id
WHERE p.active = 1
SQL;
public function resolve(QueryPlanInterface $plan): \Generator
{
assert($plan instanceof EntitySetQueryPlan);
foreach (DB::cursor(self::SQL) as $row) {
yield [
'id' => $row->id,
'name' => $row->name,
'city' => $row->city,
'country' => $row->country,
];
}
}
public function count(QueryPlanInterface $plan): int
{
return DB::scalar(
'SELECT COUNT(*) FROM (' . self::SQL . ') AS t'
);
}
}2. Register in configure()
A single discoverCustomEntitySet() call handles entity type registration, entity set creation, and resolver binding:
php
protected function configure(EdmBuilderInterface $builder): EdmBuilderInterface
{
$this->discoverCustomEntitySet(PartnerValueHelp::class);
return $builder->namespace($this->namespace());
}No registerBindings() override needed.
3. Query from UI5
The ValueHelp dialog can now query:
GET /odata/PartnerValueHelp?$filter=contains(name,'Acme')&$select=id,name,city&$top=20
GET /odata/PartnerValueHelp?$search=Berlin&$top=50
GET /odata/PartnerValueHelp(42)