Commit c3d95122 authored by Taylor Otwell's avatar Taylor Otwell

Fixing bugs… adding better pivot support.

Signed-off-by: 's avatarTaylor Otwell <taylorotwell@gmail.com>
parent c9c0ddf5
...@@ -345,6 +345,18 @@ abstract class Model { ...@@ -345,6 +345,18 @@ abstract class Model {
return new Query($this); return new Query($this);
} }
/**
* Sync the original attributes with the current attributes.
*
* @return bool
*/
final public function sync()
{
$this->original = $this->attributes;
return true;
}
/** /**
* Determine if a given attribute has changed from its original state. * Determine if a given attribute has changed from its original state.
* *
...@@ -421,6 +433,18 @@ abstract class Model { ...@@ -421,6 +433,18 @@ abstract class Model {
$this->attributes[$key] = $value; $this->attributes[$key] = $value;
} }
/**
* Remove an attribute from the model.
*
* @param string $key
*/
final public function purge($key)
{
unset($this->original[$key]);
unset($this->attributes[$key]);
}
/** /**
* Handle the dynamic retrieval of attributes and associations. * Handle the dynamic retrieval of attributes and associations.
* *
......
<?php namespace Laravel\Database\Eloquent;
class Pivot extends Model {
/**
* The name of the pivot table's table.
*
* @var string
*/
public $pivot_table;
/**
* Create a new pivot table instance.
*
* @param string $table
* @return void
*/
public function __construct($table)
{
$this->pivot_table = $table;
parent::__construct(array(), true);
}
/**
* Get the name of the pivot table.
*
* @return string
*/
public function table()
{
return $this->pivot_table;
}
}
\ No newline at end of file
...@@ -91,7 +91,7 @@ class Query { ...@@ -91,7 +91,7 @@ class Query {
// any pivot columns that are on the model. // any pivot columns that are on the model.
if ($this instanceof Relationships\Has_Many_And_Belongs_To) if ($this instanceof Relationships\Has_Many_And_Belongs_To)
{ {
$this->clean($results); $this->pivot($results);
} }
return $results; return $results;
......
<?php namespace Laravel\Database\Eloquent\Relationships; <?php namespace Laravel\Database\Eloquent\Relationships;
use Laravel\Database\Eloquent\Pivot;
class Has_Many_And_Belongs_To extends Relationship { class Has_Many_And_Belongs_To extends Relationship {
/** /**
...@@ -16,6 +18,13 @@ class Has_Many_And_Belongs_To extends Relationship { ...@@ -16,6 +18,13 @@ class Has_Many_And_Belongs_To extends Relationship {
*/ */
protected $other; protected $other;
/**
* The columns on the joining tbale that should be fetched.
*
* @var array
*/
protected $with = array();
/** /**
* Create a new many to many relationship instance. * Create a new many to many relationship instance.
* *
...@@ -120,22 +129,35 @@ class Has_Many_And_Belongs_To extends Relationship { ...@@ -120,22 +129,35 @@ class Has_Many_And_Belongs_To extends Relationship {
*/ */
protected function constrain() protected function constrain()
{ {
$other = $this->other_key();
$foreign = $this->foreign_key(); $foreign = $this->foreign_key();
$this->set_select($foreign)->set_join($this->other_key())->set_where($foreign); $this->set_select($foreign, $other)->set_join($other)->set_where($foreign);
} }
/** /**
* Set the SELECT clause on the query builder for the relationship. * Set the SELECT clause on the query builder for the relationship.
* *
* @param string $foreign * @param string $foreign
* @param string $other
* @return void * @return void
*/ */
protected function set_select($foreign) protected function set_select($foreign, $other)
{ {
$foreign = $this->joining.'.'.$foreign.' as pivot_foreign_key'; $columns = array($this->model->table().'.*');
$this->with = array_merge($this->with, array($foreign, $other));
// Since pivot tables may have extra information on them that the developer
// needs, we allow an extra array of columns to be specified that will be
// fetched from the pivot table and hydrate into the pivot model.
foreach ($this->with as $column)
{
$columns[] = $this->joining.'.'.$column.' as pivot_'.$column;
}
$this->table->select(array($this->model->table().'.*', $foreign)); $this->table->select($columns);
return $this; return $this;
} }
...@@ -201,35 +223,66 @@ class Has_Many_And_Belongs_To extends Relationship { ...@@ -201,35 +223,66 @@ class Has_Many_And_Belongs_To extends Relationship {
*/ */
public function match($relationship, &$parents, $children) public function match($relationship, &$parents, $children)
{ {
$foreign = 'pivot_foreign_key'; $foreign = $this->foreign_key();
foreach ($children as $key => $child) foreach ($children as $key => $child)
{ {
$parents[$child->$foreign]->relationships[$relationship][$child->{$child->key()}] = $child; $parents[$child->pivot->$foreign]->relationships[$relationship][$child->{$child->key()}] = $child;
// After matching the child model with its parent, we can remove the foreign key
// from the model, as it was only necessary to allow us to know which parent
// the child belongs to for eager loading and isn't necessary otherwise.
unset($child->attributes[$foreign]);
unset($child->original[$foreign]);
} }
} }
/** /**
* Clean-up any pivot columns that are on the results. * Hydrate the Pivot model on an array of results.
* *
* @param array $results * @param array $results
* @return void * @return void
*/ */
protected function clean(&$results) protected function pivot(&$results)
{ {
foreach ($results as &$result) foreach ($results as &$result)
{ {
// Every model result for a many-to-many relationship needs a Pivot instance
// to represent the pivot table's columns. Sometimes extra columns are on
// the pivot table that may need to be accessed by the developer.
$pivot = new Pivot($this->joining);
// If the attribute key starts with "pivot_", we know this is a column on
// the pivot table, so we will move it to the Pivot model and purge it
// from the model since it actually belongs to the pivot.
foreach ($result->attributes as $key => $value)
{
if (starts_with($key, 'pivot_'))
{
$pivot->{substr($key, 6)} = $value;
$result->purge($key);
}
}
// Once we have completed hydrating the pivot model instance, we'll set
// it on the result model's relationships array so the developer can
// quickly and easily access any pivot table information.
$result->relationships['pivot'] = $pivot;
$pivot->sync() and $result->sync();
} }
} }
/**
* Set the columns on the joining table that should be fetched.
*
* @param array $column
* @return Relationship
*/
public function with($columns)
{
$this->with = (is_array($columns)) ? $columns : func_get_args();
$this->set_select($this->foreign_key(), $this->other_key());
return $this;
}
/** /**
* Get the other or associated key for the relationship. * Get the other or associated key for the relationship.
* *
......
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