Skip to content

Functions and Singletons

Beyond entity sets, OData services can expose functions (parameterized queries) and singletons (named single instances).

Functions

A function is a side-effect-free operation that returns a value. Functions are declared in the schema and bound to a resolver.

Declaring a function

php
use LaravelUi5\OData\Edm\EdmFunction;
use LaravelUi5\OData\Edm\FunctionParameter;
use LaravelUi5\OData\Edm\Container\FunctionImport;
use LaravelUi5\OData\Edm\Type\PrimitiveType;
use LaravelUi5\OData\Edm\Contracts\Container\PrimitiveTypeEnum;

$int32  = new PrimitiveType(PrimitiveTypeEnum::Int32);
$string = new PrimitiveType(PrimitiveTypeEnum::String);

// Function without parameters
$countFunc = new EdmFunction(
    name: 'GetFlightCount',
    returnType: $int32,
);
$countImport = new FunctionImport('GetFlightCount', $countFunc);

// Function with parameters
$byOriginFunc = new EdmFunction(
    name: 'GetFlightsByOrigin',
    returnType: $int32,
    parameters: [new FunctionParameter('origin', $string)],
);
$byOriginImport = new FunctionImport('GetFlightsByOrigin', $byOriginFunc);

Registering on the builder

php
$builder
    ->addFunction($countFunc)
    ->addFunction($byOriginFunc)
    ->addFunctionImport($countImport)
    ->addFunctionImport($byOriginImport);

Binding a resolver

php
use LaravelUi5\OData\Service\Contracts\FunctionResolverInterface;
use LaravelUi5\OData\Service\Contracts\QueryPlanInterface;
use LaravelUi5\OData\Protocol\Planning\FunctionInvocationPlan;

protected function bindFunctions(RuntimeSchemaBuilderInterface $builder): void
{
    $container = $builder->getEdmx()->getEntityContainer();

    $builder->bindFunctionImport(
        $container->getFunctionImport('GetFlightCount'),
        new class implements FunctionResolverInterface {
            public function resolve(QueryPlanInterface $plan): mixed
            {
                return Flight::count();
            }
        },
    );

    $builder->bindFunctionImport(
        $container->getFunctionImport('GetFlightsByOrigin'),
        new class implements FunctionResolverInterface {
            public function resolve(QueryPlanInterface $plan): mixed
            {
                /** @var FunctionInvocationPlan $plan */
                $origin = $plan->parameters['origin']->value ?? null;
                return Flight::where('origin', $origin)->count();
            }
        },
    );

}

Calling functions via URL

GET /odata/GetFlightCount()
GET /odata/GetFlightsByOrigin(origin='lhr')

EdmFunction constructor parameters

ParameterTypeDefaultPurpose
namestringrequiredFunction name
isBoundboolfalseBound to a type or set
isComposableboolfalseResult can be further queried
returnType?TypeInterfacenullReturn type
returnsCollectionboolfalseReturns a collection
isReturnTypeNullablebooltrueReturn may be null
parameterslist<FunctionParameterInterface>[]Parameters
annotationslist<AnnotationInterface>[]Annotations

FunctionParameter constructor parameters

ParameterTypeDefaultPurpose
namestringrequiredParameter name
typeTypeInterfacerequiredParameter type
isCollectionboolfalseCollection parameter
isNullablebooltrueNullable parameter
facets?TypeFacetsInterfacenullType facets
annotationslist<AnnotationInterface>[]Annotations

Singletons

A singleton is a named single entity instance. It is addressable by name (not by key) and always returns one entity.

Declaring a singleton

php
use LaravelUi5\OData\Edm\Container\Singleton;

$defaultFlightSingleton = new Singleton('DefaultFlight', $flightType);

$builder->addSingleton($defaultFlightSingleton);

Binding a resolver

php
use LaravelUi5\OData\Service\Contracts\SingletonResolverInterface;

$builder->bindSingleton(
    $container->getSingleton('DefaultFlight'),
    new class implements SingletonResolverInterface {
        public function resolve(): array
        {
            return ['id' => 0, 'origin' => 'default', 'destination' => 'default'];
        }
    },
);

Querying a singleton

GET /odata/DefaultFlight
GET /odata/DefaultFlight?$select=origin,destination

The singleton appears in the service document with "kind": "Singleton".

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