<?php
namespace Illuminate\Database\Eloquent\Relations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Eloquent\Collection;
// this is a new world about this belongs Top
class BelongsTo extends Relation
{//BelongsTo extends Relation
/**
* The foreign key of the parent model.
*
* @var string
*/
protected $foreignKey;//The foreign key of the parent model.
/**
* The associated key on the parent model.
*
* @var string
*/
protected $otherKey;//The associated key on the parent model
/**
* The name of the relationship.
*
* @var string
*/
protected $relation;//The name of the relationship
/**
* Create a new belongs to relationship instance.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Model $parent
* @param string $foreignKey
* @param string $otherKey
* @param string $relation
* @return void
*/
public function __construct(Builder $query, Model $parent, $foreignKey, $otherKey, $relation)
{//Create a new belongs to relationship instance.
$this->otherKey = $otherKey;// set other key
$this->relation = $relation;// set relation
$this->foreignKey = $foreignKey;// set foreign key
parent::__construct($query, $parent);// use parent construct
}
/**
* Get the results of the relationship.
*
* @return mixed
*/
public function getResults()
{
return $this->query->first();// get the first results
}// Get the results of the relationship
/**
* Set the base constraints on the relation query.
*
* @return void
*/
public function addConstraints()
{//Set the base constraints on the relation query.
if (static::$constraints) {
// if has this constraints
// For belongs to relationships, which are essentially the inverse of has one
// or has many relationships, we need to actually query on the primary key
// of the related models matching on the foreign key that's on a parent.
$table = $this->related->getTable();
// essentially the inverse of has one or has many relationships
// get table
$this->query->where($table.'.'.$this->otherKey, '=', $this->parent->{$this->foreignKey});
}
}// add Constraints ,just like to add where condition
// set the foreign key equal the associated key.
/**
* Add the constraints for a relationship query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @param array|mixed $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
{//Add the constraints for a relationship query.
if ($parent->getQuery()->from == $query->getQuery()->from) {
return $this->getRelationQueryForSelfRelation($query, $parent, $columns);
}// if parent equal with this query from,
// use this self function to get the relationQuery
$query->select($columns);//query set the select columns
$otherKey = $this->wrap($query->getModel()->getTable().'.'.$this->otherKey);
// get the otherKey
return $query->where($this->getQualifiedForeignKey(), '=', new Expression($otherKey));
}// just like add constraints , add foreign key equal associated key in this where condition
/**
* Add the constraints for a relationship query on the same table.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @param array|mixed $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationQueryForSelfRelation(Builder $query, Builder $parent, $columns = ['*'])
{// Add the constraints for a relationship query on the same table.
$query->select($columns);// set the select columns
$query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());
// get from
$query->getModel()->setTable($hash);
// set Table
$key = $this->wrap($this->getQualifiedForeignKey());
// wrap this foreign key
return $query->where($hash.'.'.$query->getModel()->getKeyName(), '=', new Expression($key));
}// where get key
/**
* Get a relationship join table hash.
*
* @return string
*/
public function getRelationCountHash()
{// get a relationship join table hash.
return 'self_'.md5(microtime(true));
}
/**
* Set the constraints for an eager load of the relation.
*
* @param array $models
* @return void
*/
public function addEagerConstraints(array $models)
{//Set the constraints for an eager load of the relation.
// We'll grab the primary key name of the related models since it could be set to
// a non-standard name and not "id". We will then construct the constraint for
// our eagerly loading query so it returns the proper models from execution.
$key = $this->related->getTable().'.'.$this->otherKey;
// get Table key for out eagerly loading query so it returns the proper models from execution.
$this->query->whereIn($key, $this->getEagerModelKeys($models));
}// whereIn
/**
* Gather the keys from an array of related models.
*
* @param array $models
* @return array
*/
protected function getEagerModelKeys(array $models)
{//Gather the keys from an array of related models.
$keys = [];//$Keys
// First we need to gather all of the keys from the parent models so we know what
// to query for via the eager loading query. We will add them to an array then
// execute a "where in" statement to gather up all of those related records.
foreach ($models as $model) {
if (! is_null($value = $model->{$this->foreignKey})) {
$keys[] = $value;// filter the key
}// is_null
}// loop the models
// If there are no keys that were not null we will just return an array with 0 in
// it so the query doesn't fail, but will not return any results, which should
// be what this developer is expecting in a case where this happens to them.
if (count($keys) == 0) {
return [0];
}// no key return zero
return array_values(array_unique($keys));
}// just return array values
/**
* Initialize the relation on a set of models.
*
* @param array $models
* @param string $relation
* @return array
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, null);
}// models as model
return $models;//just return the models
}//Initialize the relations on a set of models.
/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{// Match the eagerly loaded results to their parents
$foreign = $this->foreignKey;
// set foreignKey
$other = $this->otherKey;// set other
// First we will get to build a dictionary of the child models by their primary
// key of the relationship, then we can easily match the children back onto
// the parents using that dictionary and the primary key of the children.
$dictionary = [];// set a store
// i like this word to set a dictionary about the children.
foreach ($results as $result) {
$dictionary[$result->getAttribute($other)] = $result;
}// loop this re
// Once we have the dictionary constructed, we can loop through all the parents
// and match back onto their children using these keys of the dictionary and
// the primary key of the children to map them onto the correct instances.
foreach ($models as $model) {
if (isset($dictionary[$model->$foreign])) {
$model->setRelation($relation, $dictionary[$model->$foreign]);
}
}//Once we have the dictionary constructed, we can loop through all the parents
// and match back onto their children using these keys of the dictionary and
// the primary key of the children to map them onto the correct instances.
return $models;
}
/**
* Associate the model instance to the given parent.
*
* @param \Illuminate\Database\Eloquent\Model|int $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function associate($model)
{//Associate the model instance to the given parent
$otherKey = ($model instanceof Model ? $model->getAttribute($this->otherKey) : $model);
// set other Key
$this->parent->setAttribute($this->foreignKey, $otherKey);
//set Attribute
if ($model instanceof Model) {
$this->parent->setRelation($this->relation, $model);
}
// set the model
return $this->parent;
}// return this parent
/**
* Dissociate previously associated model from the given parent.
*
* @return \Illuminate\Database\Eloquent\Model
*/
public function dissociate()
{
$this->parent->setAttribute($this->foreignKey, null);
// set Attribute
return $this->parent->setRelation($this->relation, null);
}// Dissociate previously associated model from the given parent.
/**
* Update the parent model on the relationship.
*
* @param array $attributes
* @return mixed
*/
public function update(array $attributes)
{// Update the parent model on the relationship.
$instance = $this->getResults();
return $instance->fill($attributes)->save();
}// get instance and fill something and save it
/**
* Get the foreign key of the relationship.
*
* @return string
*/
public function getForeignKey()
{
return $this->foreignKey;
}//Get the foreign key of the relationship
// big return
/**
* Get the fully qualified foreign key of the relationship.
*
* @return string
*/
public function getQualifiedForeignKey()
{
return $this->parent->getTable().'.'.$this->foreignKey;
}// big get
/**
* Get the associated key of the relationship.
*
* @return string
*/
public function getOtherKey()
{
return $this->otherKey;
}// just get
/**
* Get the fully qualified associated key of the relationship.
*
* @return string
*/
public function getQualifiedOtherKeyName()
{
return $this->related->getTable().'.'.$this->otherKey;
}// same
}