Core
Unified Builder Documentation
Overview
Unified Builder is the service that simplifies interaction with the FQL Manager, Elastic Search, and Eloquent systems. It is designed to be scalable, maintainable, and easy to use.
To simplify implementation, we use the Facade pattern, Factory pattern, and the Laravel container.
Flow
Facade → Factory → Queries/AggregatorsMain Components
Facade
The facade (UnifiedBuilder.php) is responsible for exposing all queries and aggregators to external modules. It is registered in the Laravel container using a provider (UnifiedBuilderServiceProvider.php).
This allows access via:
- The
app()helper - Dependency injection through
UnifiedBuilderInterface
Note: The facade contains no logic—just method calls to the factory.
Factory
The factory creates object instances (except transfer objects) with their dependencies.
Note: The factory contains no logic—only instance creation.
Transfer Objects
Unified Builder uses two transfer objects:
QueryResultAggregatorResult
These objects ensure structured data transfer without using arrays.
All methods in the Facade return one of these Transfer Objects—no other return types are allowed.
Note: Transfer Objects can be instantiated outside the factory if needed.
Queries
Queries are categorized into:
FqlQueries: Access Elastic Search (also supports MySQL)EloquentQueries: Used for MySQL (or any Eloquent-supported database)
Queries are the smallest unit in Unified Builder and form the foundation for all other components.
Aggregators
Aggregators combine multiple queries or other aggregators, returning an AggregatorResult.
Tests
Since Elastic Search is not available in our test environment, we use fixtures (snapshots of real Elastic Search data) to test queries and aggregators.
Tests verify that query/aggregator input/output remains consistent—they do not verify if Elastic Search returns the correct data.
Note: Any change to an existing query/aggregator that affects output requires a new fixture.
Implementations
Queries
1. Query Class
- Navigate to
app/Services/UnifiedBuilder/Queriesand create a folder (if it doesn’t exist) named after the domain. - Inside the folder, create a class:
EloquentQuery: Name format[QueryName]EloquentQueryFqlQuery: Name format[QueryName]FqlQuery
- Extend the appropriate abstract class:
AbstractEloquentQueryforEloquentQueryAbstractFqlQueryforFqlQuery
- Implement required methods:
getName(): Returns a unique query name.getAllowedInputs(): Defines allowed input parameters.getRequiredInputs(): Defines mandatory input parameters.buildQuery(): Implements query logic.execute(): Executes the query.executePagination(): (Not implemented yet)buildQueryResult(): Converts data into aQueryResultobject.
2. Factory
- In
UnifiedBuilderFactory.php, add a method:public function create[QueryClassName](): QueryClassName - Ensure the correct dependencies are injected.
- For
FqlQuery, injectFqlManagerusing:
$this->getContainer()->get(ElasticSearch::class) - For
3. Facade
- In
UnifiedBuilderInterface.php, add:public function [queryMethodName](): QueryClassName; - In
UnifiedBuilder.php, implement the method:return $this->getFactory()->create[QueryClassName]();
4. Tests
Refer to existing tests in tests/Feature/Services/UnifiedBuilder/Queries.
Aggregators
1. Aggregator Class
- Navigate to
app/Services/UnifiedBuilder/Aggregatorsand create a folder named after the domain. - Inside the folder, create a class:
[AggregatorName]Aggregator. - Extend
AbstractAggregator. - Implement required methods:
getName(): Returns a unique aggregator name.getAllowedInputs(): Defines allowed input parameters.getRequiredInputs(): Defines mandatory input parameters.aggregate(): Returns data forAggregatorResultBuilder.
Result Builder
Unified Builder provides a generic result builder. If needed, a custom result builder can be created (TBA).
2. Factory
- In
UnifiedBuilderFactory.php, add a method:public function create[AggregatorClassName](): AggregatorClassName - Inject dependencies:
ResultBuilder- Queries array
- Aggregators array
3. Facade
- In
UnifiedBuilderInterface.php, add:public function [aggregatorMethodName](): AggregatorClassName; - In
UnifiedBuilder.php, implement the method:return $this->getFactory()->create[AggregatorClassName]();
4. Tests
Refer to existing tests in tests/Feature/Services/UnifiedBuilder/Aggregators.
Usage
1. Dependency Injection (Recommended)
Use UnifiedBuilderInterface in your class constructor:
public function __construct(UnifiedBuilderInterface $unifiedBuilder) {}2. Laravel app() Method
Use inside a method:
$unifiedBuilder = app(UnifiedBuilderInterface::class);Providing Inputs & Options
$unifiedBuilder->someAggregator()->addInput(QueryClass::InputConst, value);
$unifiedBuilder->someAggregator()->addOption(AggregatorClass::OptionConst, value);Executing Queries & Aggregators
$queryResult = $unifiedBuilder->someQuery()->result();
$aggregatorResult = $unifiedBuilder->someAggregator()->result();TBA Sections
- Fixtures
- How to access queries inside an aggregator
- How to set an FQL to an aggregator
- How to build a custom result builder