MorphToMany.php 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. namespace Illuminate\Database\Eloquent\Relations;
  3. use Illuminate\Support\Arr;
  4. use Illuminate\Database\Eloquent\Model;
  5. use Illuminate\Database\Eloquent\Builder;
  6. class MorphToMany extends BelongsToMany
  7. {
  8. /**
  9. * The type of the polymorphic relation.
  10. *
  11. * @var string
  12. */
  13. protected $morphType;
  14. /**
  15. * The class name of the morph type constraint.
  16. *
  17. * @var string
  18. */
  19. protected $morphClass;
  20. /**
  21. * Indicates if we are connecting the inverse of the relation.
  22. *
  23. * This primarily affects the morphClass constraint.
  24. *
  25. * @var bool
  26. */
  27. protected $inverse;
  28. /**
  29. * Create a new morph to many relationship instance.
  30. *
  31. * @param \Illuminate\Database\Eloquent\Builder $query
  32. * @param \Illuminate\Database\Eloquent\Model $parent
  33. * @param string $name
  34. * @param string $table
  35. * @param string $foreignPivotKey
  36. * @param string $relatedPivotKey
  37. * @param string $parentKey
  38. * @param string $relatedKey
  39. * @param string $relationName
  40. * @param bool $inverse
  41. * @return void
  42. */
  43. public function __construct(Builder $query, Model $parent, $name, $table, $foreignPivotKey,
  44. $relatedPivotKey, $parentKey, $relatedKey, $relationName = null, $inverse = false)
  45. {
  46. $this->inverse = $inverse;
  47. $this->morphType = $name.'_type';
  48. $this->morphClass = $inverse ? $query->getModel()->getMorphClass() : $parent->getMorphClass();
  49. parent::__construct(
  50. $query, $parent, $table, $foreignPivotKey,
  51. $relatedPivotKey, $parentKey, $relatedKey, $relationName
  52. );
  53. }
  54. /**
  55. * Set the where clause for the relation query.
  56. *
  57. * @return $this
  58. */
  59. protected function addWhereConstraints()
  60. {
  61. parent::addWhereConstraints();
  62. $this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
  63. return $this;
  64. }
  65. /**
  66. * Set the constraints for an eager load of the relation.
  67. *
  68. * @param array $models
  69. * @return void
  70. */
  71. public function addEagerConstraints(array $models)
  72. {
  73. parent::addEagerConstraints($models);
  74. $this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
  75. }
  76. /**
  77. * Create a new pivot attachment record.
  78. *
  79. * @param int $id
  80. * @param bool $timed
  81. * @return array
  82. */
  83. protected function baseAttachRecord($id, $timed)
  84. {
  85. return Arr::add(
  86. parent::baseAttachRecord($id, $timed), $this->morphType, $this->morphClass
  87. );
  88. }
  89. /**
  90. * Add the constraints for a relationship count query.
  91. *
  92. * @param \Illuminate\Database\Eloquent\Builder $query
  93. * @param \Illuminate\Database\Eloquent\Builder $parentQuery
  94. * @param array|mixed $columns
  95. * @return \Illuminate\Database\Eloquent\Builder
  96. */
  97. public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
  98. {
  99. return parent::getRelationExistenceQuery($query, $parentQuery, $columns)->where(
  100. $this->table.'.'.$this->morphType, $this->morphClass
  101. );
  102. }
  103. /**
  104. * Create a new query builder for the pivot table.
  105. *
  106. * @return \Illuminate\Database\Query\Builder
  107. */
  108. protected function newPivotQuery()
  109. {
  110. return parent::newPivotQuery()->where($this->morphType, $this->morphClass);
  111. }
  112. /**
  113. * Create a new pivot model instance.
  114. *
  115. * @param array $attributes
  116. * @param bool $exists
  117. * @return \Illuminate\Database\Eloquent\Relations\Pivot
  118. */
  119. public function newPivot(array $attributes = [], $exists = false)
  120. {
  121. $using = $this->using;
  122. $pivot = $using ? $using::fromRawAttributes($this->parent, $attributes, $this->table, $exists)
  123. : MorphPivot::fromAttributes($this->parent, $attributes, $this->table, $exists);
  124. $pivot->setPivotKeys($this->foreignPivotKey, $this->relatedPivotKey)
  125. ->setMorphType($this->morphType)
  126. ->setMorphClass($this->morphClass);
  127. return $pivot;
  128. }
  129. /**
  130. * Get the pivot columns for the relation.
  131. *
  132. * "pivot_" is prefixed at each column for easy removal later.
  133. *
  134. * @return array
  135. */
  136. protected function aliasedPivotColumns()
  137. {
  138. $defaults = [$this->foreignPivotKey, $this->relatedPivotKey, $this->morphType];
  139. return collect(array_merge($defaults, $this->pivotColumns))->map(function ($column) {
  140. return $this->table.'.'.$column.' as pivot_'.$column;
  141. })->unique()->all();
  142. }
  143. /**
  144. * Get the foreign key "type" name.
  145. *
  146. * @return string
  147. */
  148. public function getMorphType()
  149. {
  150. return $this->morphType;
  151. }
  152. /**
  153. * Get the class name of the parent model.
  154. *
  155. * @return string
  156. */
  157. public function getMorphClass()
  158. {
  159. return $this->morphClass;
  160. }
  161. }