123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- <?php
- // Copyright 2019 Hackware SpA <human@hackware.cl>
- // "Hackware Web Services Core" is released under the MIT License terms.
- namespace Hawese\Core;
- use Illuminate\Support\Collection;
- /**
- * Colleciton of TableModels
- *
- * Currently only supports appendForeignObjects() and get()
- */
- class TableModelCollection
- {
- private $collection;
- private $model;
- public function __construct($collection, $model)
- {
- $this->model = $model;
- $this->collection = $collection->map(function ($object) {
- return new $this->model($object);
- });
- }
- private function mapForeignCollections(array $attributes) : array
- {
- return array_combine(
- $attributes,
- array_map(function ($attribute) {
- $foreign_key = $this->model::guessFK($attribute);
- return $this->getForeignCollection($foreign_key);
- }, $attributes)
- );
- }
- private function getForeignCollection(
- string $foreign_key
- ) : TableModelCollection {
- $ids = $this->collection->pluck($foreign_key)->unique()->values();
- $foreign_model = $this->model::$foreign_keys[$foreign_key];
- return $foreign_model::processCollection(
- $foreign_model::select()
- ->whereIn($foreign_model::$primary_key, $ids)
- ->get()
- );
- }
- /**
- * Match $foreign_collections element PK with $object FK and return it.
- *
- * @param TableModel $object Single object to compare with.
- * @param TableModelCollection[] $foregin_collections map of collections.
- * @param array $match Associative array containing `attribute`, `key` &
- * `model`.
- */
- private function findForeignObject(
- TableModel $object,
- array $foreign_collections,
- array $match
- ) : object {
- return $foreign_collections[$match['attribute']]->get()->first(
- function ($foreign_object) use ($object, $match) {
- $object_fk = $object->{$match['key']};
- $foreign_pk = $foreign_object->{
- $match['model']::$primary_key
- };
- return $object_fk === $foreign_pk;
- }
- );
- }
- /**
- * Appends $foreign_keys based objects to each object on collection.
- *
- * This method edits the original $collection and is 'fluent'.
- * This avoids the N+1 queries antipattern.
- */
- public function appendForeignObjects(array $attributes) : self
- {
- $foreign_collections = $this->mapForeignCollections($attributes);
- $this->collection = $this->collection->map(
- function ($object) use ($attributes, $foreign_collections) {
- foreach ($attributes as $attribute) {
- $object->append($attribute);
- $foreign_key = $this->model::guessFK($attribute);
- $object->{$attribute} = $this->findForeignObject(
- $object,
- $foreign_collections,
- [
- 'attribute' => $attribute,
- 'key' => $foreign_key,
- 'model' => $this->model::$foreign_keys[$foreign_key]
- ]
- );
- }
- return $object;
- }
- );
- return $this;
- }
- public function get() : Collection
- {
- return $this->collection;
- }
- }
|