Skip to content

Commit b53834f

Browse files
committed
Load eager relations and pivot recursive
1 parent 0a668d3 commit b53834f

File tree

1 file changed

+109
-5
lines changed

1 file changed

+109
-5
lines changed

src/ElasticquentTrait.php

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Elasticquent;
44

55
use Exception;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Eloquent\Relations\Relation;
68

79
/**
810
* Elasticquent Trait
@@ -583,11 +585,10 @@ public static function typeExists()
583585
*/
584586
public function newFromHitBuilder($hit = array())
585587
{
586-
$instance = $this->newInstance(array(), true);
587-
$keyname = $instance->getKeyName();
588+
$keyname = $this->getKeyName();
588589

589-
$attributes = $hit['_source'];
590-
$attributes[$keyname] = $hit['_id'];
590+
$attributes = $hit['_source'];
591+
$attributes[$keyname] = is_numeric($hit['_id']) ? intval($hit['_id']) : $hit['_id'];
591592

592593
// Add fields to attributes
593594
if (isset($hit['fields'])) {
@@ -596,7 +597,7 @@ public function newFromHitBuilder($hit = array())
596597
}
597598
}
598599

599-
$instance->setRawAttributes((array)$attributes, true);
600+
$instance = $this::newFromBuilderRecursive($this, $attributes);
600601

601602
// In addition to setting the attributes
602603
// from the index, we will set the score as well.
@@ -614,4 +615,107 @@ public function newFromHitBuilder($hit = array())
614615
return $instance;
615616
}
616617

618+
/**
619+
* Create a new model instance that is existing recursive.
620+
*
621+
* @param \Illuminate\Database\Eloquent\Model $model
622+
* @param array $attributes
623+
* @param \Illuminate\Database\Eloquent\Relation $parentRelation
624+
* @return static
625+
*/
626+
public static function newFromBuilderRecursive(Model $model, array $attributes = [], Relation $parentRelation = null)
627+
{
628+
$instance = $model->newInstance([], $exists = true);
629+
630+
$instance->setRawAttributes((array)$attributes, $sync = true);
631+
632+
// Load relations recursive
633+
static::loadRelationsAttributesRecursive($instance);
634+
// Load pivot
635+
static::loadPivotAttribute($instance, $parentRelation);
636+
637+
return $instance;
638+
}
639+
640+
/**
641+
* Create a collection of models from plain arrays recursive.
642+
*
643+
* @param \Illuminate\Database\Eloquent\Model $model
644+
* @param \Illuminate\Database\Eloquent\Relation $parentRelation
645+
* @param array $items
646+
* @return \Illuminate\Database\Eloquent\Collection
647+
*/
648+
public static function hydrateRecursive(Model $model, array $items, Relation $parentRelation = null)
649+
{
650+
$instance = $model;
651+
652+
$items = array_map(function ($item) use ($instance, $parentRelation) {
653+
return static::newFromBuilderRecursive($instance, $item, $parentRelation);
654+
}, $items);
655+
656+
return $instance->newCollection($items);
657+
}
658+
659+
/**
660+
* Get the relations attributes from a model.
661+
*
662+
* @param \Illuminate\Database\Eloquent\Model $model
663+
*/
664+
public static function loadRelationsAttributesRecursive(Model $model)
665+
{
666+
$attributes = $model->getAttributes();
667+
668+
foreach ($attributes as $key => $value) {
669+
if (method_exists($model, $key)) {
670+
$relation = $model->$key();
671+
if ($relation instanceof Relation) {
672+
// Check if the relation field is single model or collections
673+
if (!static::isMultiLevelArray($value)) {
674+
$value = [$value];
675+
}
676+
$models = static::hydrateRecursive($relation->getModel(), $value, $relation);
677+
// Unset attribute before match relation
678+
unset($model[$key]);
679+
$relation->match([$model], $models, $key);
680+
}
681+
}
682+
}
683+
}
684+
685+
/**
686+
* Get the pivot attribute from a model.
687+
*
688+
* @param \Illuminate\Database\Eloquent\Model $model
689+
* @param \Illuminate\Database\Eloquent\Relation $parentRelation
690+
*/
691+
public static function loadPivotAttribute(Model $model, Relation $parentRelation = null)
692+
{
693+
$attributes = $model->getAttributes();
694+
695+
foreach ($attributes as $key => $value) {
696+
if ($key === 'pivot') {
697+
unset($model[$key]);
698+
$pivot = $parentRelation->newExistingPivot($value);
699+
$model->setRelation($key, $pivot);
700+
}
701+
}
702+
}
703+
704+
/**
705+
* Check if an array is multi-level array like [[id], [id], [id]].
706+
*
707+
* For detect if a relation field is single model or collections.
708+
*
709+
* @param array $array
710+
* @return boolean
711+
*/
712+
private static function isMultiLevelArray(array $array)
713+
{
714+
foreach ($array as $key => $value) {
715+
if (!is_array($value)) {
716+
return false;
717+
}
718+
}
719+
return true;
720+
}
617721
}

0 commit comments

Comments
 (0)