As of FiQueLa 3.0, custom functions are static-only utility classes that implement one of two interfaces and are registered with the globalDocumentation Index
Fetch the complete documentation index at: https://docs.fiquela.io/llms.txt
Use this file to discover all available pages before exploring further.
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
| Interface | Namespace | Use when |
|---|---|---|
ScalarFunction | FQL\Functions\Core\ScalarFunction | Your function runs once per row (e.g. LOWER, CONCAT, ROUND). |
AggregateFunction | FQL\Functions\Core\AggregateFunction | Your function accumulates state across a group (e.g. SUM, AVG, GROUP_CONCAT). |
__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 fromsrc/Functions/functions.neon for built-ins.
| Method | Description |
|---|---|
register(class-string $class) | Register a new scalar or aggregate function. |
override(class-string $class) | Replace an existing function (built-in or user-registered) with the same name. |
unregister(string $name) | Remove a previously registered function. |
loadConfig(string $path) | Bulk-load function classes from a NEON config file. |
has(string $name) | Check whether a function is registered. |
isAggregate(string $name) | Check whether a registered function is an aggregate. |
all() | Return the full registry map. |
reset() | Reset the registry to the built-in defaults. |
setCacheDir(string $path) | Configure the resolved class-map cache directory. |
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:| 2.x | 3.0 replacement |
|---|---|
BaseFunction, SingleFieldFunction, MultipleFieldsFunction, NoFieldFunction, abstract AggregateFunction, BaseFunctionByReference, SingleFieldFunctionByReference, SingleFieldAggregateFunction | Implement Functions\Core\ScalarFunction or Functions\Core\AggregateFunction directly. |
Interface\Invokable, InvokableAggregate, InvokableByReference, InvokableNoField, IncrementalAggregate | New static-only contracts in Functions\Core. |
Interface\Query::custom(Function $fn) | FunctionRegistry::register(MyFn::class) at bootstrap. |
applyValue() / applyValues() instance methods | A single static execute(...) method. |