Skip to content

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)

OData: MIT | Core: BSL 1.1 | SDK: Commercial License