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/Aggregators

Main 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:

  • QueryResult
  • AggregatorResult

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

  1. Navigate to app/Services/UnifiedBuilder/Queries and create a folder (if it doesn’t exist) named after the domain.
  2. Inside the folder, create a class:
    • EloquentQuery: Name format [QueryName]EloquentQuery
    • FqlQuery: Name format [QueryName]FqlQuery
  3. Extend the appropriate abstract class:
    • AbstractEloquentQuery for EloquentQuery
    • AbstractFqlQuery for FqlQuery
  4. 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 a QueryResult object.

2. Factory

  1. In UnifiedBuilderFactory.php, add a method:
    public function create[QueryClassName](): QueryClassName
  2. Ensure the correct dependencies are injected.
    • For FqlQuery, inject FqlManager using:
    $this->getContainer()->get(ElasticSearch::class)

3. Facade

  1. In UnifiedBuilderInterface.php, add:
    public function [queryMethodName](): QueryClassName;
  2. 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

  1. Navigate to app/Services/UnifiedBuilder/Aggregators and create a folder named after the domain.
  2. Inside the folder, create a class: [AggregatorName]Aggregator.
  3. Extend AbstractAggregator.
  4. Implement required methods:
    • getName(): Returns a unique aggregator name.
    • getAllowedInputs(): Defines allowed input parameters.
    • getRequiredInputs(): Defines mandatory input parameters.
    • aggregate(): Returns data for AggregatorResultBuilder.

Result Builder

Unified Builder provides a generic result builder. If needed, a custom result builder can be created (TBA).

2. Factory

  1. In UnifiedBuilderFactory.php, add a method:
    public function create[AggregatorClassName](): AggregatorClassName
  2. Inject dependencies:
    • ResultBuilder
    • Queries array
    • Aggregators array

3. Facade

  1. In UnifiedBuilderInterface.php, add:
    public function [aggregatorMethodName](): AggregatorClassName;
  2. In UnifiedBuilder.php, implement the method:
    return $this->getFactory()->create[AggregatorClassName]();

4. Tests

Refer to existing tests in tests/Feature/Services/UnifiedBuilder/Aggregators.


Usage

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
Previous
Tenancy Manager