Skip to main content
As of FiQueLa 3.0, custom functions are static-only utility classes that implement one of two interfaces and are registered with the global FunctionRegistry. Once registered, they are available everywhere — both in the fluent API and in FQL string queries — and dispatch goes through the same expression evaluator as the built-ins.

Function contracts

Each class is a static-only container — no constructor, no __invoke. A scalar function exposes name() and a static execute(...). An aggregate function exposes name() plus static initial(), accumulate(...), and finalize(...) methods.

Example: scalar function

The following example appends a _custom suffix to any string value.

Example: aggregate function

The following example computes a population standard deviation across a group.

Registering your function

Register the class once at application bootstrap — typically right after the Composer autoloader. The registry is process-global and bootstraps from src/Functions/functions.neon for built-ins.
The registry exposes a small public API: If you try to register a class that is missing one of the contracts, the registry throws FQL\Exception\FunctionRegistrationException. Calling an unknown function at runtime throws FQL\Exception\UnknownFunctionException.

Using a registered function

Once registered, the function is available by name in both APIs.

FQL string syntax

Fluent API

The fluent helpers parse SQL expression strings, so you can call your custom function inline anywhere a built-in works:
Custom functions are dispatched through Sql\Provider::parseExpression() together with built-ins. The same code path powers both the fluent helpers and the FQL string parser, so a registered function behaves identically in either form.

Migrating from 2.x

If you wrote custom functions for FiQueLa 2.x, the following pieces have been removed and replaced: