Commit 94948cf6 authored by Taylor Otwell's avatar Taylor Otwell

Fix Eloquent eager loading matching.

parent b65fa704
...@@ -66,12 +66,11 @@ class Query { ...@@ -66,12 +66,11 @@ class Query {
* Get all of the model results for the query. * Get all of the model results for the query.
* *
* @param array $columns * @param array $columns
* @param bool $keyed
* @return array * @return array
*/ */
public function get($columns = array('*'), $keyed = true) public function get($columns = array('*'))
{ {
return $this->hydrate($this->model, $this->table->get($columns), $keyed); return $this->hydrate($this->model, $this->table->get($columns));
} }
/** /**
...@@ -100,10 +99,9 @@ class Query { ...@@ -100,10 +99,9 @@ class Query {
* *
* @param Model $model * @param Model $model
* @param array $results * @param array $results
* @param bool $keyed
* @return array * @return array
*/ */
public function hydrate($model, $results, $keyed = true) public function hydrate($model, $results)
{ {
$class = get_class($model); $class = get_class($model);
...@@ -128,17 +126,7 @@ class Query { ...@@ -128,17 +126,7 @@ class Query {
$new->original = $new->attributes; $new->original = $new->attributes;
// Typically, the resulting models are keyed by their primary key, but it $models[] = $new;
// may be useful to not do this in some circumstances such as when we
// are eager loading a *-to-* relationships which has duplicates.
if ($keyed)
{
$models[$result[$this->model->key()]] = $new;
}
else
{
$models[] = $new;
}
} }
if (count($results) > 0) if (count($results) > 0)
...@@ -199,17 +187,7 @@ class Query { ...@@ -199,17 +187,7 @@ class Query {
$query->initialize($results, $relationship); $query->initialize($results, $relationship);
// If we're eager loading a many-to-many relationship we will disable $query->match($relationship, $results, $query->get());
// the primary key indexing on the hydration since there could be
// roles shared across users and we don't want to overwrite.
if ( ! $query instanceof Has_Many_And_Belongs_To)
{
$query->match($relationship, $results, $query->get());
}
else
{
$query->match($relationship, $results, $query->get(array('*'), false));
}
} }
/** /**
......
...@@ -87,9 +87,14 @@ class Belongs_To extends Relationship { ...@@ -87,9 +87,14 @@ class Belongs_To extends Relationship {
foreach ($children as &$child) foreach ($children as &$child)
{ {
if (array_key_exists($child->$foreign, $parents)) $parent = array_first($parents, function($k, $v) use ($child, $foreign)
{ {
$child->relationships[$relationship] = $parents[$child->$foreign]; return $v->get_key() == $child->$foreign;
});
if ( ! is_null($parent))
{
$child->relationships[$relationship] = $parent;
} }
} }
} }
......
...@@ -91,9 +91,14 @@ class Has_Many extends Has_One_Or_Many { ...@@ -91,9 +91,14 @@ class Has_Many extends Has_One_Or_Many {
{ {
$foreign = $this->foreign_key(); $foreign = $this->foreign_key();
foreach ($children as $key => $child) foreach ($parents as &$parent)
{ {
$parents[$child->$foreign]->relationships[$relationship][$child->get_key()] = $child; $matching = array_filter($children, function($v) use ($parent, $foreign)
{
return $v->$foreign == $parent->get_key();
});
$parent->relationships[$relationship] = $matching;
} }
} }
......
...@@ -311,7 +311,7 @@ class Has_Many_And_Belongs_To extends Relationship { ...@@ -311,7 +311,7 @@ class Has_Many_And_Belongs_To extends Relationship {
*/ */
public function eagerly_constrain($results) public function eagerly_constrain($results)
{ {
$this->table->where_in($this->joining.'.'.$this->foreign_key(), array_keys($results)); $this->table->where_in($this->joining.'.'.$this->foreign_key(), $this->keys($results));
} }
/** /**
...@@ -325,14 +325,14 @@ class Has_Many_And_Belongs_To extends Relationship { ...@@ -325,14 +325,14 @@ class Has_Many_And_Belongs_To extends Relationship {
{ {
$foreign = $this->foreign_key(); $foreign = $this->foreign_key();
// For each child we'll just get the parent that connects to the child and set the foreach ($parents as &$parent)
// child model on the relationship array using the keys. Once we're done looping
// through the children all of the proper relations will be set.
foreach ($children as $key => $child)
{ {
$parent =& $parents[$child->pivot->$foreign]; $matching = array_filter($children, function($v) use ($parent, $foreign)
{
return $v->pivot->$foreign == $parent->get_key();
});
$parent->relationships[$relationship][$child->{$child->key()}] = $child; $parent->relationships[$relationship] = $matching;
} }
} }
......
...@@ -38,9 +38,14 @@ class Has_One extends Has_One_Or_Many { ...@@ -38,9 +38,14 @@ class Has_One extends Has_One_Or_Many {
{ {
$foreign = $this->foreign_key(); $foreign = $this->foreign_key();
foreach ($children as $key => $child) foreach ($parents as &$parent)
{ {
$parents[$child->$foreign]->relationships[$relationship] = $child; $matching = array_first($children, function($k, $v) use ($parent, $foreign)
{
return $v->$foreign == $parent->get_key();
});
$parent->relationships[$relationship] = $matching;
} }
} }
......
...@@ -53,7 +53,7 @@ class Has_One_Or_Many extends Relationship { ...@@ -53,7 +53,7 @@ class Has_One_Or_Many extends Relationship {
*/ */
public function eagerly_constrain($results) public function eagerly_constrain($results)
{ {
$this->table->where_in($this->foreign_key(), array_keys($results)); $this->table->where_in($this->foreign_key(), $this->keys($results));
} }
} }
\ No newline at end of file
...@@ -101,4 +101,22 @@ abstract class Relationship extends Query { ...@@ -101,4 +101,22 @@ abstract class Relationship extends Query {
return static::foreign($this->base, $this->foreign); return static::foreign($this->base, $this->foreign);
} }
/**
* Gather all the primary keys from a result set.
*
* @param array $results
* @return array
*/
public function keys($results)
{
$keys = array();
foreach ($results as $result)
{
$keys[] = $result->get_key();
}
return array_unique($keys);
}
} }
\ No newline at end of file
...@@ -13,7 +13,7 @@ class Error { ...@@ -13,7 +13,7 @@ class Error {
{ {
static::log($exception); static::log($exception);
ob_get_level() and ob_end_clean(); //ob_get_level() and ob_end_clean();
// If detailed errors are enabled, we'll just format the exception into // If detailed errors are enabled, we'll just format the exception into
// a simple error message and display it on the screen. We don't use a // a simple error message and display it on the screen. We don't use a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment