Added Eloquent 2.
Signed-off-by: Taylor Otwell <taylorotwell@gmail.com>
This commit is contained in:
parent
3de0d1af66
commit
d6d667af90
|
@ -126,6 +126,7 @@
|
||||||
'Cookie' => 'Laravel\\Cookie',
|
'Cookie' => 'Laravel\\Cookie',
|
||||||
'Crypter' => 'Laravel\\Crypter',
|
'Crypter' => 'Laravel\\Crypter',
|
||||||
'DB' => 'Laravel\\Database',
|
'DB' => 'Laravel\\Database',
|
||||||
|
'Eloquent' => 'Laravel\\Database\\Eloquent\\Model',
|
||||||
'Event' => 'Laravel\\Event',
|
'Event' => 'Laravel\\Event',
|
||||||
'File' => 'Laravel\\File',
|
'File' => 'Laravel\\File',
|
||||||
'Filter' => 'Laravel\\Routing\\Filter',
|
'Filter' => 'Laravel\\Routing\\Filter',
|
||||||
|
|
|
@ -0,0 +1,528 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent;
|
||||||
|
|
||||||
|
use Laravel\Database;
|
||||||
|
use Eloquent\Relationships\Has_Many_And_Belongs_To;
|
||||||
|
|
||||||
|
abstract class Model {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All of the model's attributes.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $attributes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model's attributes in their original state.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $original = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The relationships that have been loaded for the query.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $relationships = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the model exists in the database.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $exists = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The relationships that should be eagerly loaded.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $includes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary key for the model on the database table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $key = 'id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are accessible for mass assignment.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $accessible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the model has update and creation timestamps.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public static $timestamps = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the database connection that should be used for the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the sequence associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $sequence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Eloquent model instance.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @param bool $exists
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($attributes = array(), $exists = false)
|
||||||
|
{
|
||||||
|
$this->exists = $exists;
|
||||||
|
|
||||||
|
$this->fill($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the accessible attributes for the given model.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function accessible($attributes)
|
||||||
|
{
|
||||||
|
static::$accessible = $attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hydrate the model with an array of attributes.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function fill($attributes)
|
||||||
|
{
|
||||||
|
$attributes = (array) $attributes;
|
||||||
|
|
||||||
|
foreach ($attributes as $key => $value)
|
||||||
|
{
|
||||||
|
// If the "accessible" property is an array, the developer is limiting the
|
||||||
|
// attributes that may be mass assigned, and we need to verify that the
|
||||||
|
// current attribute is included in that list of allowed attributes.
|
||||||
|
if (is_array(static::$accessible))
|
||||||
|
{
|
||||||
|
if (in_array($key, static::$accessible))
|
||||||
|
{
|
||||||
|
$this->$key = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the "accessible" property is not an array, no attributes have been
|
||||||
|
// white-listed and we are free to set the value of the attribute to
|
||||||
|
// the value that has been passed into the method without a check.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->$key = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the original attribute values have not been set, we will set them to
|
||||||
|
// the values passed to this method allowing us to quickly check if the
|
||||||
|
// model has changed since hydration of the original instance.
|
||||||
|
if (count($this->original) === 0)
|
||||||
|
{
|
||||||
|
$this->original = $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a model by its primary key.
|
||||||
|
*
|
||||||
|
* @param string $id
|
||||||
|
* @param array $columns
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public static function find($id, $columns = array('*'))
|
||||||
|
{
|
||||||
|
$model = new static;
|
||||||
|
|
||||||
|
return $model->query()->where(static::$key, '=', $id)->first($columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the models in the database.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function all()
|
||||||
|
{
|
||||||
|
$model = new static;
|
||||||
|
|
||||||
|
return $model->query()->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The relationships that should be eagerly loaded by the query.
|
||||||
|
*
|
||||||
|
* @param array $includes
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function _with($includes)
|
||||||
|
{
|
||||||
|
$this->includes = (array) $includes;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the query for a one-to-one association.
|
||||||
|
*
|
||||||
|
* @param string $model
|
||||||
|
* @param string $foreign
|
||||||
|
* @return Relationship
|
||||||
|
*/
|
||||||
|
public function has_one($model, $foreign = null)
|
||||||
|
{
|
||||||
|
return $this->has_one_or_many(__FUNCTION__, $model, $foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the query for a one-to-many association.
|
||||||
|
*
|
||||||
|
* @param string $model
|
||||||
|
* @param string $foreign
|
||||||
|
* @return Relationship
|
||||||
|
*/
|
||||||
|
public function has_many($model, $foreign = null)
|
||||||
|
{
|
||||||
|
return $this->has_one_or_many(__FUNCTION__, $model, $foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the query for a one-to-one / many association.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param string $model
|
||||||
|
* @param string $foreign
|
||||||
|
* @return Relationship
|
||||||
|
*/
|
||||||
|
protected function has_one_or_many($type, $model, $foreign)
|
||||||
|
{
|
||||||
|
if ($type == 'has_one')
|
||||||
|
{
|
||||||
|
return new Relationships\Has_One($this, $model, $foreign);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new Relationships\Has_Many($this, $model, $foreign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the query for a one-to-one (inverse) relationship.
|
||||||
|
*
|
||||||
|
* @param string $model
|
||||||
|
* @param string $foreign
|
||||||
|
* @return Relationship
|
||||||
|
*/
|
||||||
|
public function belongs_to($model, $foreign = null)
|
||||||
|
{
|
||||||
|
// If no foreign key is specified for the relationship, we will assume that the
|
||||||
|
// name of the calling function matches the foreign key. For example, if the
|
||||||
|
// calling function is "manager", we'll assume the key is "manager_id".
|
||||||
|
if (is_null($foreign))
|
||||||
|
{
|
||||||
|
list(, $caller) = debug_backtrace(false);
|
||||||
|
|
||||||
|
$foreign = "{$caller['function']}_id";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Relationships\Belongs_To($this, $model, $foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the query for a many-to-many relationship.
|
||||||
|
*
|
||||||
|
* @param string $model
|
||||||
|
* @param string $table
|
||||||
|
* @param string $foreign
|
||||||
|
* @param string $other
|
||||||
|
* @return Relationship
|
||||||
|
*/
|
||||||
|
public function has_many_and_belongs_to($model, $table, $foreign = null, $other = null)
|
||||||
|
{
|
||||||
|
return new Has_Many_And_Belongs_To($this, $model, $table, $foreign, $other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the model instance to the database.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
if ( ! $this->dirty()) return true;
|
||||||
|
|
||||||
|
if (static::$timestamps)
|
||||||
|
{
|
||||||
|
$this->timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the model exists, we only need to update it in the database, and the update
|
||||||
|
// will be considered successful if there is one affected row returned from the
|
||||||
|
// fluent query instance. We'll set the where condition automatically.
|
||||||
|
if ($this->exists)
|
||||||
|
{
|
||||||
|
$query = $this->query()->where(static::$key, '=', $this->get_key());
|
||||||
|
|
||||||
|
$result = $query->update($this->get_dirty()) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the model does not exist, we will insert the record and retrieve the last
|
||||||
|
// insert ID that is associated with the model. If the ID returned is numeric
|
||||||
|
// then we can consider the insert successful.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$id = $this->query()->insert_get_id($this->attributes, $this->sequence());
|
||||||
|
|
||||||
|
$this->set_key($id);
|
||||||
|
|
||||||
|
$this->exists = $result = is_numeric($this->get_key());
|
||||||
|
}
|
||||||
|
|
||||||
|
// After the model has been "saved", we will set the original attributes to
|
||||||
|
// match the current attributes so the model will not be viewed as being
|
||||||
|
// dirty and subsequent calls won't hit the database.
|
||||||
|
$this->original = $this->attributes;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the update and creation timestamps on the model.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function timestamp()
|
||||||
|
{
|
||||||
|
$this->updated_at = $this->get_timestamp();
|
||||||
|
|
||||||
|
if ( ! $this->exists) $this->created_at = $this->updated_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current timestamp in its storable form.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function get_timestamp()
|
||||||
|
{
|
||||||
|
return date('Y-m-d H:i:s');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new fluent query builder instance for the model.
|
||||||
|
*
|
||||||
|
* @return Query
|
||||||
|
*/
|
||||||
|
protected function query()
|
||||||
|
{
|
||||||
|
return new Query($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a given attribute has changed from its original state.
|
||||||
|
*
|
||||||
|
* @param string $attribute
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function changed($attribute)
|
||||||
|
{
|
||||||
|
array_get($this->attributes, $attribute) !== array_get($this->original, $attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the model has been changed from its original state.
|
||||||
|
*
|
||||||
|
* Models that haven't been persisted to storage are always considered dirty.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function dirty()
|
||||||
|
{
|
||||||
|
return ! $this->exists or $this->original !== $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the dirty attributes for the model.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_dirty()
|
||||||
|
{
|
||||||
|
return array_diff_assoc($this->attributes, $this->original);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the primary key for the model.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function get_key()
|
||||||
|
{
|
||||||
|
return $this->get_attribute(static::$key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of the primary key for the model.
|
||||||
|
*
|
||||||
|
* @param int $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set_key($value)
|
||||||
|
{
|
||||||
|
return $this->set_attribute(static::$key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a given attribute from the model.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
*/
|
||||||
|
public function get_attribute($key)
|
||||||
|
{
|
||||||
|
return $this->attributes[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an attribute's value on the model.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param mixed $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set_attribute($key, $value)
|
||||||
|
{
|
||||||
|
$this->attributes[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the dynamic retrieval of attributes and associations.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __get($key)
|
||||||
|
{
|
||||||
|
// First we will check to see if the requested key is an already loaded
|
||||||
|
// relationship and return it if it is. All relationships are stored
|
||||||
|
// in the special relationships array so they are not persisted.
|
||||||
|
if (array_key_exists($key, $this->relationships))
|
||||||
|
{
|
||||||
|
return $this->relationships[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the item is not a loaded relationship, it may be a relationship
|
||||||
|
// that hasn't been loaded yet. If it is, we will lazy load it and
|
||||||
|
// set the value of the relationship in the relationship array.
|
||||||
|
elseif (method_exists($this, $key))
|
||||||
|
{
|
||||||
|
return $this->relationships[$key] = $this->$key()->results();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally we will just assume the requested key is just a regular
|
||||||
|
// attribute and attempt to call the getter method for it, which
|
||||||
|
// will fall into the __call method if one doesn't exist.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $this->{"get_{$key}"}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the dynamic setting of attributes.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param mixed $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __set($key, $value)
|
||||||
|
{
|
||||||
|
$this->{"set_{$key}"}($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle dynamic method calls on the model.
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param array $parameters
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __call($method, $parameters)
|
||||||
|
{
|
||||||
|
// If the method is actually the name of a static property on the model we'll
|
||||||
|
// return the value of the static property. This makes it convenient for
|
||||||
|
// relationships to access these values off of the instances.
|
||||||
|
if (in_array($method, array('key', 'table', 'connection', 'sequence')))
|
||||||
|
{
|
||||||
|
return static::$$method;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some methods need to be accessed both staticly and non-staticly so we'll
|
||||||
|
// keep underscored methods of those methods and intercept calls to them
|
||||||
|
// here so they can be called either way on the model instance.
|
||||||
|
if (in_array($method, array('with')))
|
||||||
|
{
|
||||||
|
return call_user_func_array(array($this, '_'.$method), $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First we want to see if the method is a getter / setter for an attribute.
|
||||||
|
// If it is, we'll call the basic getter and setter method for the model
|
||||||
|
// to perform the appropriate action based on the method.
|
||||||
|
if (starts_with($method, 'get_'))
|
||||||
|
{
|
||||||
|
return $this->get_attribute(substr($method, 4));
|
||||||
|
}
|
||||||
|
elseif (starts_with($method, 'set_'))
|
||||||
|
{
|
||||||
|
return $this->set_attribute(substr($method, 4), $parameters[0]);
|
||||||
|
}
|
||||||
|
// Finally we will assume that the method is actually the beginning of a
|
||||||
|
// query, such as "where", and will create a new query instance and
|
||||||
|
// call the method on the query instance, returning it after.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return call_user_func_array(array($this->query(), $method), $parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically handle static method calls on the model.
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param array $parameters
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function __callStatic($method, $parameters)
|
||||||
|
{
|
||||||
|
$model = get_called_class();
|
||||||
|
|
||||||
|
return call_user_func_array(array(new $model, $method), $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,246 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent; use Laravel\Database;
|
||||||
|
|
||||||
|
class Query {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model instance being queried.
|
||||||
|
*
|
||||||
|
* @var Model
|
||||||
|
*/
|
||||||
|
public $model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fluent query builder for the query instance.
|
||||||
|
*
|
||||||
|
* @var Query
|
||||||
|
*/
|
||||||
|
public $table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The relationships that should be eagerly loaded by the query.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $includes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The methods that should be returned from the fluent query builder.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $passthru = array(
|
||||||
|
'lists', 'only', 'insert', 'update', 'increment', 'decrement',
|
||||||
|
'count', 'min', 'max', 'avg', 'sum'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creat a new query instance for a model.
|
||||||
|
*
|
||||||
|
* @param Model $model
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($model)
|
||||||
|
{
|
||||||
|
$this->model = ($model instanceof Model) ? $model : new $model;
|
||||||
|
|
||||||
|
$this->table = $this->query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first model result for the query.
|
||||||
|
*
|
||||||
|
* @param array $columns
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function first($columns = array('*'))
|
||||||
|
{
|
||||||
|
$results = $this->hydrate($this->model, $this->table->take(1)->get($columns, false));
|
||||||
|
|
||||||
|
return (is_array($results)) ? head($results) : $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the model results for the query.
|
||||||
|
*
|
||||||
|
* @param array $columns
|
||||||
|
* @param bool $include
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get($columns = array('*'), $include = true)
|
||||||
|
{
|
||||||
|
$results = $this->hydrate($this->model, $this->table->get($columns));
|
||||||
|
|
||||||
|
if ($include)
|
||||||
|
{
|
||||||
|
foreach ($this->model_includes() as $relationship => $constraints)
|
||||||
|
{
|
||||||
|
// If the relationship is nested, we will skip laoding it here and let
|
||||||
|
// the load method parse and set the nested eager loads on the right
|
||||||
|
// relationship when it is getting ready to eager laod it.
|
||||||
|
if (str_contains($relationship, '.'))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->load($results, $relationship, $constraints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hydrate an array of models from the given results.
|
||||||
|
*
|
||||||
|
* @param Model $model
|
||||||
|
* @param array $results
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function hydrate($model, $results)
|
||||||
|
{
|
||||||
|
$class = get_class($model);
|
||||||
|
|
||||||
|
$models = array();
|
||||||
|
|
||||||
|
// We'll spin through the array of database results and hydrate a model
|
||||||
|
// for each one of the records. We will also set the "exists" flag to
|
||||||
|
// "true" so that the model will be updated when it is saved.
|
||||||
|
foreach ((array) $results as $result)
|
||||||
|
{
|
||||||
|
$result = (array) $result;
|
||||||
|
|
||||||
|
$models[$result[$this->model->key()]] = new $class($result, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $models;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hydrate an eagerly loaded relationship on the model results.
|
||||||
|
*
|
||||||
|
* @param array $results
|
||||||
|
* @param string $relationship
|
||||||
|
* @param array|null $constraints
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function load(&$results, $relationship, $constraints)
|
||||||
|
{
|
||||||
|
$query = $this->model->$relationship();
|
||||||
|
|
||||||
|
$query->model->includes = $this->nested_includes($relationship);
|
||||||
|
|
||||||
|
// We'll remove any of the where clauses from the relationship to give
|
||||||
|
// the relationship the opportunity to set the constraints for an
|
||||||
|
// eager relationship using a separate, specific method.
|
||||||
|
$query->table->reset_where();
|
||||||
|
|
||||||
|
$query->eagerly_constrain($results);
|
||||||
|
|
||||||
|
// Constraints may be specified in-line for the eager load by passing
|
||||||
|
// a Closure as the value portion of the eager load. We can use the
|
||||||
|
// query builder's nested query support to add the constraints.
|
||||||
|
if ( ! is_null($constraints))
|
||||||
|
{
|
||||||
|
$query->table->where_nested($constraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before matching the models, we will initialize the relationship
|
||||||
|
// to either null for single-value relationships or an array for
|
||||||
|
// the multi-value relationships as their baseline value.
|
||||||
|
$query->initialize($results, $relationship);
|
||||||
|
|
||||||
|
$query->match($relationship, $results, $query->get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gather the nested includes for a given relationship.
|
||||||
|
*
|
||||||
|
* @param string $relationship
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function nested_includes($relationship)
|
||||||
|
{
|
||||||
|
$nested = array();
|
||||||
|
|
||||||
|
foreach ($this->model_includes() as $include => $constraints)
|
||||||
|
{
|
||||||
|
// To get the nested includes, we want to find any includes that begin
|
||||||
|
// the relationship and a dot, then we will strip off the leading
|
||||||
|
// nesting indicator and set the include in the array.
|
||||||
|
if (starts_with($include, $relationship.'.'))
|
||||||
|
{
|
||||||
|
$nested[substr($include, strlen($relationship.'.'))] = $constraints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the eagerly loaded relationships for the model.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function model_includes()
|
||||||
|
{
|
||||||
|
$includes = array();
|
||||||
|
|
||||||
|
foreach ($this->model->includes as $relationship => $constraints)
|
||||||
|
{
|
||||||
|
// When eager loading relationships, constraints may be set on the eager
|
||||||
|
// load definition; however, is none are set, we need to swap the key
|
||||||
|
// and the value of the array since there are no constraints.
|
||||||
|
if (is_numeric($relationship))
|
||||||
|
{
|
||||||
|
list($relationship, $constraints) = array($constraints, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
$includes[$relationship] = $constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $includes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a fluent query builder for the model.
|
||||||
|
*
|
||||||
|
* @return Query
|
||||||
|
*/
|
||||||
|
protected function query()
|
||||||
|
{
|
||||||
|
return $this->connection()->table($this->model->table());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the database connection for the model.
|
||||||
|
*
|
||||||
|
* @return Connection
|
||||||
|
*/
|
||||||
|
protected function connection()
|
||||||
|
{
|
||||||
|
return Database::connection($this->model->connection());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle dynamic method calls to the query.
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param array $parameters
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __call($method, $parameters)
|
||||||
|
{
|
||||||
|
$result = call_user_func_array(array($this->table, $method), $parameters);
|
||||||
|
|
||||||
|
// Some methods may get their results straight from the fluent query
|
||||||
|
// builder, such as the aggregate methods. If the called method is
|
||||||
|
// one of these, we will return the result straight away.
|
||||||
|
if (in_array($method, $this->passthru))
|
||||||
|
{
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent\Relationships;
|
||||||
|
|
||||||
|
class Belongs_To extends Relationship {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the properly hydrated results for the relationship.
|
||||||
|
*
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function results()
|
||||||
|
{
|
||||||
|
return parent::first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proper constraints on the relationship table.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function constrain()
|
||||||
|
{
|
||||||
|
$foreign = $this->base->get_attribute($this->foreign);
|
||||||
|
|
||||||
|
$this->table->where($this->base->key(), '=', $foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a relationship on an array of parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param string $relationship
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function initialize(&$parents, $relationship)
|
||||||
|
{
|
||||||
|
foreach ($parents as &$parent)
|
||||||
|
{
|
||||||
|
$parent->relationships[$relationship] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proper constraints on the relationship table for an eager load.
|
||||||
|
*
|
||||||
|
* @param array $results
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function eagerly_constrain($results)
|
||||||
|
{
|
||||||
|
$keys = array();
|
||||||
|
|
||||||
|
// Inverse one-to-many relationships require us to gather the keys from the
|
||||||
|
// parent models and use those keys when setting the constraint since we
|
||||||
|
// are looking for the parent of a child model in this relationship.
|
||||||
|
foreach ($results as $result)
|
||||||
|
{
|
||||||
|
$keys[] = $result->{$this->foreign_key()};
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->table->where_in($this->model->key(), array_unique($keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match eagerly loaded child models to their parent models.
|
||||||
|
*
|
||||||
|
* @param array $children
|
||||||
|
* @param array $parents
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function match($relationship, &$children, $parents)
|
||||||
|
{
|
||||||
|
$foreign = $this->foreign_key();
|
||||||
|
|
||||||
|
foreach ($children as &$child)
|
||||||
|
{
|
||||||
|
if (array_key_exists($child->$foreign, $parents))
|
||||||
|
{
|
||||||
|
$child->relationships[$relationship] = $parents[$child->$foreign];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent\Relationships;
|
||||||
|
|
||||||
|
class Has_Many extends Has_One_Or_Many {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the properly hydrated results for the relationship.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function results()
|
||||||
|
{
|
||||||
|
return parent::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a relationship on an array of parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param string $relationship
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function initialize(&$parents, $relationship)
|
||||||
|
{
|
||||||
|
foreach ($parents as &$parent)
|
||||||
|
{
|
||||||
|
$parent->relationships[$relationship] = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match eagerly loaded child models to their parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param array $children
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function match($relationship, &$parents, $children)
|
||||||
|
{
|
||||||
|
$foreign = $this->foreign_key();
|
||||||
|
|
||||||
|
foreach ($children as $key => $child)
|
||||||
|
{
|
||||||
|
$parents[$child->$foreign]->relationships[$relationship][$child->get_key()] = $child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,239 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent\Relationships;
|
||||||
|
|
||||||
|
class Has_Many_And_Belongs_To extends Relationship {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the intermediate, joining table.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $joining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The other or "associated" key. This is the foreign key of the related model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $other;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new many to many relationship instance.
|
||||||
|
*
|
||||||
|
* @param Model $model
|
||||||
|
* @param string $associated
|
||||||
|
* @param string $table
|
||||||
|
* @param string $foreign
|
||||||
|
* @param string $other
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($model, $associated, $table, $foreign, $other)
|
||||||
|
{
|
||||||
|
$this->other = $other;
|
||||||
|
|
||||||
|
$this->joining = $table;
|
||||||
|
|
||||||
|
parent::__construct($model, $associated, $foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the properly hydrated results for the relationship.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function results()
|
||||||
|
{
|
||||||
|
return parent::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new record into the joining table of the association.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function add($id)
|
||||||
|
{
|
||||||
|
return $this->insert_joining($this->join_record($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new record for the association.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function insert($attributes)
|
||||||
|
{
|
||||||
|
$id = $this->table->insert_get_id($attributes, $this->model->sequence());
|
||||||
|
|
||||||
|
$result = $this->insert_joining($this->join_record($id));
|
||||||
|
|
||||||
|
return is_numeric($id) and $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all of the records from the joining table for the model.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
return $this->joining_table()->where($this->foreign_key(), '=', $this->base->get_key())->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an array representing a new joining record for the association.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function join_record($id)
|
||||||
|
{
|
||||||
|
return array($this->foreign_key() => $this->base->get_key(), $this->other_key() => $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new record into the joining table of the association.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function insert_joining($attributes)
|
||||||
|
{
|
||||||
|
return $this->joining_table()->insert($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a fluent query for the joining table of the relationship.
|
||||||
|
*
|
||||||
|
* @return Query
|
||||||
|
*/
|
||||||
|
protected function joining_table()
|
||||||
|
{
|
||||||
|
return $this->connection()->table($this->joining);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proper constraints on the relationship table.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function constrain()
|
||||||
|
{
|
||||||
|
$foreign = $this->foreign_key();
|
||||||
|
|
||||||
|
$this->set_select($foreign)->set_join($this->other_key())->set_where($foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the SELECT clause on the query builder for the relationship.
|
||||||
|
*
|
||||||
|
* @param string $foreign
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function set_select($foreign)
|
||||||
|
{
|
||||||
|
$foreign = $this->joining.'.'.$foreign.' as eloquent_foreign_key';
|
||||||
|
|
||||||
|
$this->table->select(array($this->model->table().'.*', $foreign));
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the JOIN clause on the query builder for the relationship.
|
||||||
|
*
|
||||||
|
* @param string $other
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function set_join($other)
|
||||||
|
{
|
||||||
|
$this->table->join($this->joining, $this->associated_key(), '=', $this->joining.'.'.$other);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the WHERE clause on the query builder for the relationship.
|
||||||
|
*
|
||||||
|
* @param string $foreign
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function set_where($foreign)
|
||||||
|
{
|
||||||
|
$this->table->where($this->joining.'.'.$foreign, '=', $this->base->get_key());
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a relationship on an array of parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param string $relationship
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function initialize(&$parents, $relationship)
|
||||||
|
{
|
||||||
|
foreach ($parents as &$parent)
|
||||||
|
{
|
||||||
|
$parent->relationships[$relationship] = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proper constraints on the relationship table for an eager load.
|
||||||
|
*
|
||||||
|
* @param array $results
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function eagerly_constrain($results)
|
||||||
|
{
|
||||||
|
$this->table->where_in($this->joining.'.'.$this->foreign_key(), array_keys($results));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match eagerly loaded child models to their parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param array $children
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function match($relationship, &$parents, $children)
|
||||||
|
{
|
||||||
|
$foreign = 'eloquent_foreign_key';
|
||||||
|
|
||||||
|
foreach ($children as $key => $child)
|
||||||
|
{
|
||||||
|
$parents[$child->$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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the other or associated key for the relationship.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function other_key()
|
||||||
|
{
|
||||||
|
return Relationship::foreign($this->model, $this->other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the fully qualified associated table's primary key.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function associated_key()
|
||||||
|
{
|
||||||
|
return $this->model->table().'.'.$this->model->key();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent\Relationships;
|
||||||
|
|
||||||
|
class Has_One extends Has_One_Or_Many {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the properly hydrated results for the relationship.
|
||||||
|
*
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function results()
|
||||||
|
{
|
||||||
|
return parent::first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a relationship on an array of parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param string $relationship
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function initialize(&$parents, $relationship)
|
||||||
|
{
|
||||||
|
foreach ($parents as &$parent)
|
||||||
|
{
|
||||||
|
$parent->relationships[$relationship] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match eagerly loaded child models to their parent models.
|
||||||
|
*
|
||||||
|
* @param array $parents
|
||||||
|
* @param array $children
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function match($relationship, &$parents, $children)
|
||||||
|
{
|
||||||
|
$foreign = $this->foreign_key();
|
||||||
|
|
||||||
|
foreach ($children as $key => $child)
|
||||||
|
{
|
||||||
|
$parents[$child->$foreign]->relationships[$relationship] = $child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent\Relationships; use Eloquent\Model;
|
||||||
|
|
||||||
|
class Has_One_Or_Many extends Relationship {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new record for the association.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function insert($attributes)
|
||||||
|
{
|
||||||
|
$attributes[$this->foreign_key()] = $this->base->get_key();
|
||||||
|
|
||||||
|
return parent::insert($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proper constraints on the relationship table.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function constrain()
|
||||||
|
{
|
||||||
|
$this->table->where($this->foreign_key(), '=', $this->base->get_key());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proper constraints on the relationship table for an eager load.
|
||||||
|
*
|
||||||
|
* @param array $results
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function eagerly_constrain($results)
|
||||||
|
{
|
||||||
|
$this->table->where_in($this->foreign_key(), array_keys($results));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php namespace Laravel\Database\Eloquent\Relationships; use Eloquent\Model, Eloquent\Query;
|
||||||
|
|
||||||
|
abstract class Relationship extends Query {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base model for the relationship.
|
||||||
|
*
|
||||||
|
* @var Model
|
||||||
|
*/
|
||||||
|
protected $base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new has one or many association instance.
|
||||||
|
*
|
||||||
|
* @param Model $model
|
||||||
|
* @param string $associated
|
||||||
|
* @param string $foreign
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($model, $associated, $foreign)
|
||||||
|
{
|
||||||
|
$this->foreign = $foreign;
|
||||||
|
|
||||||
|
// We will go ahead and set the model and associated instances on the relationship
|
||||||
|
// to match the relationship targets passed in from the model. These will allow
|
||||||
|
// us to gather more inforamtion on the relationship.
|
||||||
|
$this->model = ($associated instanceof Model) ? $associated : new $associated;
|
||||||
|
|
||||||
|
if ($model instanceof Model)
|
||||||
|
{
|
||||||
|
$this->base = $model;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->base = new $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next we'll set the fluent query builder for the relationship and constrain
|
||||||
|
// the query such that it only returns the models that are appropriate for
|
||||||
|
// the relationship, typically by setting the foreign key.
|
||||||
|
$this->table = $this->query();
|
||||||
|
|
||||||
|
$this->constrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the foreign key name for the given model.
|
||||||
|
*
|
||||||
|
* @param string $model
|
||||||
|
* @param string $foreign
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function foreign($model, $foreign = null)
|
||||||
|
{
|
||||||
|
if ( ! is_null($foreign)) return $foreign;
|
||||||
|
|
||||||
|
// If the model is an object, we will simply get the class of the object and
|
||||||
|
// then take the basename, which is simply the object name minus the
|
||||||
|
// namespace, and we'll append "_id" to the name.
|
||||||
|
if (is_object($model))
|
||||||
|
{
|
||||||
|
$model = get_class($model);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strtolower(basename($model).'_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the foreign key for the relationship.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function foreign_key()
|
||||||
|
{
|
||||||
|
return Relationship::foreign($this->base, $this->foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue