-
Type: Task
-
Resolution: Fixed
-
Priority: Unknown
-
Affects Version/s: None
-
Component/s: Laravel
-
None
-
PHP Drivers
Detailed Design (Laravel ORM)
Builder
The builder interface supports adding stages to a pipeline and then returning that pipeline once it’s complete:
interface PipelineBuilder
{ // Factory to start out with an existing pipeline and append to it public static function fromPipeline(Pipeline|PipelineBuilder $pipeline): static; public function addFields(...$fields): static; public function match(...$fields): static; public function sort(...$specification): static; public function limit(int $limit): static; public function getPipeline(): Pipeline; }
The builder can be used to assemble aggregation pipelines without starting from a model. The resulting Pipeline instance can then be converted to an array (for usage in the Collection::aggregate method) or used further. The following example shows how to create an example pipeline:
// $oneMonthAgo is initialised to today - 1 month $pipeline = $builder ->match(status: 'enabled', createdAt: gte($oneMonthAgo)) ->addFields( filteredList: filter( input: arrayFieldPath(items'), cond: eq(variable('this.status'), 'enabled'), ), ) ->sort(createdAt: -1) ->limit(5) ->getPipeline();
Model integration
The main entry point for aggregation is through the Model class in Laravel, which is extended by every database model class. The main entry point is an aggregate method that takes a pipeline and returns a Laravel Collection instance with the results:
interface SupportsAggregation { public function aggregate(array|Pipeline $pipeline, array $options): Collection; }
// Usage
$allResults = MyModel::aggregate($builder);
Due to aggregate already being present in Laravel, the actual implementation will have to also accept a string parameter. In that case, we defer to the existing implementation of aggregate instead of running an aggregation pipeline.
Choosing result class
By default the results of an aggregation pipeline are returned using the default type map of the underlying client object. However, users can choose to have their results hydrated into a model class of their choosing. In the builder, the asModel() method can be used to change the output model:
MyModel ::aggregate(pipeline(...)) ->asModel(AggregatedMyModel::class)
->first();
This instructs the builder to return results as instances of the AggregatedMyModel class, allowing for further processing. Since these models will not be mapped to an existing document in the database, any Active Record functionality must be disabled (i.e. save() should not actually try to persist changes to the database).
- related to
-
PHPORM-166 Remove mongodb/mongo-php-builder package suggestion
- Blocked