PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php

https://gitlab.com/hatemdigify/digifyblog
PHP | 310 lines | 126 code | 46 blank | 138 comment | 8 complexity | 3a3efefb365a5bcb1e26c6ad7950d161 MD5 | raw file
  1. <?php
  2. namespace Illuminate\Database\Eloquent\Relations;
  3. use Illuminate\Database\Eloquent\Model;
  4. use Illuminate\Database\Eloquent\Builder;
  5. use Illuminate\Database\Query\Expression;
  6. use Illuminate\Database\Eloquent\Collection;
  7. class BelongsTo extends Relation
  8. {
  9. /**
  10. * The foreign key of the parent model.
  11. *
  12. * @var string
  13. */
  14. protected $foreignKey;
  15. /**
  16. * The associated key on the parent model.
  17. *
  18. * @var string
  19. */
  20. protected $otherKey;
  21. /**
  22. * The name of the relationship.
  23. *
  24. * @var string
  25. */
  26. protected $relation;
  27. /**
  28. * Create a new belongs to relationship instance.
  29. *
  30. * @param \Illuminate\Database\Eloquent\Builder $query
  31. * @param \Illuminate\Database\Eloquent\Model $parent
  32. * @param string $foreignKey
  33. * @param string $otherKey
  34. * @param string $relation
  35. * @return void
  36. */
  37. public function __construct(Builder $query, Model $parent, $foreignKey, $otherKey, $relation)
  38. {
  39. $this->otherKey = $otherKey;
  40. $this->relation = $relation;
  41. $this->foreignKey = $foreignKey;
  42. parent::__construct($query, $parent);
  43. }
  44. /**
  45. * Get the results of the relationship.
  46. *
  47. * @return mixed
  48. */
  49. public function getResults()
  50. {
  51. return $this->query->first();
  52. }
  53. /**
  54. * Set the base constraints on the relation query.
  55. *
  56. * @return void
  57. */
  58. public function addConstraints()
  59. {
  60. if (static::$constraints) {
  61. // For belongs to relationships, which are essentially the inverse of has one
  62. // or has many relationships, we need to actually query on the primary key
  63. // of the related models matching on the foreign key that's on a parent.
  64. $table = $this->related->getTable();
  65. $this->query->where($table.'.'.$this->otherKey, '=', $this->parent->{$this->foreignKey});
  66. }
  67. }
  68. /**
  69. * Add the constraints for a relationship query.
  70. *
  71. * @param \Illuminate\Database\Eloquent\Builder $query
  72. * @param \Illuminate\Database\Eloquent\Builder $parent
  73. * @param array|mixed $columns
  74. * @return \Illuminate\Database\Eloquent\Builder
  75. */
  76. public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
  77. {
  78. if ($parent->getQuery()->from == $query->getQuery()->from) {
  79. return $this->getRelationQueryForSelfRelation($query, $parent, $columns);
  80. }
  81. $query->select($columns);
  82. $otherKey = $this->wrap($query->getModel()->getTable().'.'.$this->otherKey);
  83. return $query->where($this->getQualifiedForeignKey(), '=', new Expression($otherKey));
  84. }
  85. /**
  86. * Add the constraints for a relationship query on the same table.
  87. *
  88. * @param \Illuminate\Database\Eloquent\Builder $query
  89. * @param \Illuminate\Database\Eloquent\Builder $parent
  90. * @param array|mixed $columns
  91. * @return \Illuminate\Database\Eloquent\Builder
  92. */
  93. public function getRelationQueryForSelfRelation(Builder $query, Builder $parent, $columns = ['*'])
  94. {
  95. $query->select($columns);
  96. $query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());
  97. $query->getModel()->setTable($hash);
  98. $key = $this->wrap($this->getQualifiedForeignKey());
  99. return $query->where($hash.'.'.$query->getModel()->getKeyName(), '=', new Expression($key));
  100. }
  101. /**
  102. * Get a relationship join table hash.
  103. *
  104. * @return string
  105. */
  106. public function getRelationCountHash()
  107. {
  108. return 'self_'.md5(microtime(true));
  109. }
  110. /**
  111. * Set the constraints for an eager load of the relation.
  112. *
  113. * @param array $models
  114. * @return void
  115. */
  116. public function addEagerConstraints(array $models)
  117. {
  118. // We'll grab the primary key name of the related models since it could be set to
  119. // a non-standard name and not "id". We will then construct the constraint for
  120. // our eagerly loading query so it returns the proper models from execution.
  121. $key = $this->related->getTable().'.'.$this->otherKey;
  122. $this->query->whereIn($key, $this->getEagerModelKeys($models));
  123. }
  124. /**
  125. * Gather the keys from an array of related models.
  126. *
  127. * @param array $models
  128. * @return array
  129. */
  130. protected function getEagerModelKeys(array $models)
  131. {
  132. $keys = [];
  133. // First we need to gather all of the keys from the parent models so we know what
  134. // to query for via the eager loading query. We will add them to an array then
  135. // execute a "where in" statement to gather up all of those related records.
  136. foreach ($models as $model) {
  137. if (! is_null($value = $model->{$this->foreignKey})) {
  138. $keys[] = $value;
  139. }
  140. }
  141. // If there are no keys that were not null we will just return an array with 0 in
  142. // it so the query doesn't fail, but will not return any results, which should
  143. // be what this developer is expecting in a case where this happens to them.
  144. if (count($keys) == 0) {
  145. return [0];
  146. }
  147. return array_values(array_unique($keys));
  148. }
  149. /**
  150. * Initialize the relation on a set of models.
  151. *
  152. * @param array $models
  153. * @param string $relation
  154. * @return array
  155. */
  156. public function initRelation(array $models, $relation)
  157. {
  158. foreach ($models as $model) {
  159. $model->setRelation($relation, null);
  160. }
  161. return $models;
  162. }
  163. /**
  164. * Match the eagerly loaded results to their parents.
  165. *
  166. * @param array $models
  167. * @param \Illuminate\Database\Eloquent\Collection $results
  168. * @param string $relation
  169. * @return array
  170. */
  171. public function match(array $models, Collection $results, $relation)
  172. {
  173. $foreign = $this->foreignKey;
  174. $other = $this->otherKey;
  175. // First we will get to build a dictionary of the child models by their primary
  176. // key of the relationship, then we can easily match the children back onto
  177. // the parents using that dictionary and the primary key of the children.
  178. $dictionary = [];
  179. foreach ($results as $result) {
  180. $dictionary[$result->getAttribute($other)] = $result;
  181. }
  182. // Once we have the dictionary constructed, we can loop through all the parents
  183. // and match back onto their children using these keys of the dictionary and
  184. // the primary key of the children to map them onto the correct instances.
  185. foreach ($models as $model) {
  186. if (isset($dictionary[$model->$foreign])) {
  187. $model->setRelation($relation, $dictionary[$model->$foreign]);
  188. }
  189. }
  190. return $models;
  191. }
  192. /**
  193. * Associate the model instance to the given parent.
  194. *
  195. * @param \Illuminate\Database\Eloquent\Model|int $model
  196. * @return \Illuminate\Database\Eloquent\Model
  197. */
  198. public function associate($model)
  199. {
  200. $otherKey = ($model instanceof Model ? $model->getAttribute($this->otherKey) : $model);
  201. $this->parent->setAttribute($this->foreignKey, $otherKey);
  202. if ($model instanceof Model) {
  203. $this->parent->setRelation($this->relation, $model);
  204. }
  205. return $this->parent;
  206. }
  207. /**
  208. * Dissociate previously associated model from the given parent.
  209. *
  210. * @return \Illuminate\Database\Eloquent\Model
  211. */
  212. public function dissociate()
  213. {
  214. $this->parent->setAttribute($this->foreignKey, null);
  215. return $this->parent->setRelation($this->relation, null);
  216. }
  217. /**
  218. * Update the parent model on the relationship.
  219. *
  220. * @param array $attributes
  221. * @return mixed
  222. */
  223. public function update(array $attributes)
  224. {
  225. $instance = $this->getResults();
  226. return $instance->fill($attributes)->save();
  227. }
  228. /**
  229. * Get the foreign key of the relationship.
  230. *
  231. * @return string
  232. */
  233. public function getForeignKey()
  234. {
  235. return $this->foreignKey;
  236. }
  237. /**
  238. * Get the fully qualified foreign key of the relationship.
  239. *
  240. * @return string
  241. */
  242. public function getQualifiedForeignKey()
  243. {
  244. return $this->parent->getTable().'.'.$this->foreignKey;
  245. }
  246. /**
  247. * Get the associated key of the relationship.
  248. *
  249. * @return string
  250. */
  251. public function getOtherKey()
  252. {
  253. return $this->otherKey;
  254. }
  255. /**
  256. * Get the fully qualified associated key of the relationship.
  257. *
  258. * @return string
  259. */
  260. public function getQualifiedOtherKeyName()
  261. {
  262. return $this->related->getTable().'.'.$this->otherKey;
  263. }
  264. }