HasRelationships.php 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. <?php
  2. namespace Illuminate\Database\Eloquent\Concerns;
  3. use Illuminate\Support\Arr;
  4. use Illuminate\Support\Str;
  5. use Illuminate\Database\Eloquent\Model;
  6. use Illuminate\Database\Eloquent\Builder;
  7. use Illuminate\Database\Eloquent\Collection;
  8. use Illuminate\Database\Eloquent\Relations\HasOne;
  9. use Illuminate\Database\Eloquent\Relations\HasMany;
  10. use Illuminate\Database\Eloquent\Relations\MorphTo;
  11. use Illuminate\Database\Eloquent\Relations\MorphOne;
  12. use Illuminate\Database\Eloquent\Relations\Relation;
  13. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  14. use Illuminate\Database\Eloquent\Relations\MorphMany;
  15. use Illuminate\Database\Eloquent\Relations\MorphToMany;
  16. use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  17. use Illuminate\Database\Eloquent\Relations\HasManyThrough;
  18. trait HasRelationships
  19. {
  20. /**
  21. * The loaded relationships for the model.
  22. *
  23. * @var array
  24. */
  25. protected $relations = [];
  26. /**
  27. * The relationships that should be touched on save.
  28. *
  29. * @var array
  30. */
  31. protected $touches = [];
  32. /**
  33. * The many to many relationship methods.
  34. *
  35. * @var array
  36. */
  37. public static $manyMethods = [
  38. 'belongsToMany', 'morphToMany', 'morphedByMany',
  39. 'guessBelongsToManyRelation', 'findFirstMethodThatIsntRelation',
  40. ];
  41. /**
  42. * Define a one-to-one relationship.
  43. *
  44. * @param string $related
  45. * @param string $foreignKey
  46. * @param string $localKey
  47. * @return \Illuminate\Database\Eloquent\Relations\HasOne
  48. */
  49. public function hasOne($related, $foreignKey = null, $localKey = null)
  50. {
  51. $instance = $this->newRelatedInstance($related);
  52. $foreignKey = $foreignKey ?: $this->getForeignKey();
  53. $localKey = $localKey ?: $this->getKeyName();
  54. return $this->newHasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
  55. }
  56. /**
  57. * Instantiate a new HasOne relationship.
  58. *
  59. * @param \Illuminate\Database\Eloquent\Builder $query
  60. * @param \Illuminate\Database\Eloquent\Model $parent
  61. * @param string $foreignKey
  62. * @param string $localKey
  63. * @return \Illuminate\Database\Eloquent\Relations\HasOne
  64. */
  65. protected function newHasOne(Builder $query, Model $parent, $foreignKey, $localKey)
  66. {
  67. return new HasOne($query, $parent, $foreignKey, $localKey);
  68. }
  69. /**
  70. * Define a polymorphic one-to-one relationship.
  71. *
  72. * @param string $related
  73. * @param string $name
  74. * @param string $type
  75. * @param string $id
  76. * @param string $localKey
  77. * @return \Illuminate\Database\Eloquent\Relations\MorphOne
  78. */
  79. public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
  80. {
  81. $instance = $this->newRelatedInstance($related);
  82. list($type, $id) = $this->getMorphs($name, $type, $id);
  83. $table = $instance->getTable();
  84. $localKey = $localKey ?: $this->getKeyName();
  85. return $this->newMorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
  86. }
  87. /**
  88. * Instantiate a new MorphOne relationship.
  89. *
  90. * @param \Illuminate\Database\Eloquent\Builder $query
  91. * @param \Illuminate\Database\Eloquent\Model $parent
  92. * @param string $type
  93. * @param string $id
  94. * @param string $localKey
  95. * @return \Illuminate\Database\Eloquent\Relations\MorphOne
  96. */
  97. protected function newMorphOne(Builder $query, Model $parent, $type, $id, $localKey)
  98. {
  99. return new MorphOne($query, $parent, $type, $id, $localKey);
  100. }
  101. /**
  102. * Define an inverse one-to-one or many relationship.
  103. *
  104. * @param string $related
  105. * @param string $foreignKey
  106. * @param string $ownerKey
  107. * @param string $relation
  108. * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
  109. */
  110. public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)
  111. {
  112. // If no relation name was given, we will use this debug backtrace to extract
  113. // the calling method's name and use that as the relationship name as most
  114. // of the time this will be what we desire to use for the relationships.
  115. if (is_null($relation)) {
  116. $relation = $this->guessBelongsToRelation();
  117. }
  118. $instance = $this->newRelatedInstance($related);
  119. // If no foreign key was supplied, we can use a backtrace to guess the proper
  120. // foreign key name by using the name of the relationship function, which
  121. // when combined with an "_id" should conventionally match the columns.
  122. if (is_null($foreignKey)) {
  123. $foreignKey = Str::snake($relation).'_'.$instance->getKeyName();
  124. }
  125. // Once we have the foreign key names, we'll just create a new Eloquent query
  126. // for the related models and returns the relationship instance which will
  127. // actually be responsible for retrieving and hydrating every relations.
  128. $ownerKey = $ownerKey ?: $instance->getKeyName();
  129. return $this->newBelongsTo(
  130. $instance->newQuery(), $this, $foreignKey, $ownerKey, $relation
  131. );
  132. }
  133. /**
  134. * Instantiate a new BelongsTo relationship.
  135. *
  136. * @param \Illuminate\Database\Eloquent\Builder $query
  137. * @param \Illuminate\Database\Eloquent\Model $child
  138. * @param string $foreignKey
  139. * @param string $ownerKey
  140. * @param string $relation
  141. * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
  142. */
  143. protected function newBelongsTo(Builder $query, Model $child, $foreignKey, $ownerKey, $relation)
  144. {
  145. return new BelongsTo($query, $child, $foreignKey, $ownerKey, $relation);
  146. }
  147. /**
  148. * Define a polymorphic, inverse one-to-one or many relationship.
  149. *
  150. * @param string $name
  151. * @param string $type
  152. * @param string $id
  153. * @param string $ownerKey
  154. * @return \Illuminate\Database\Eloquent\Relations\MorphTo
  155. */
  156. public function morphTo($name = null, $type = null, $id = null, $ownerKey = null)
  157. {
  158. // If no name is provided, we will use the backtrace to get the function name
  159. // since that is most likely the name of the polymorphic interface. We can
  160. // use that to get both the class and foreign key that will be utilized.
  161. $name = $name ?: $this->guessBelongsToRelation();
  162. list($type, $id) = $this->getMorphs(
  163. Str::snake($name), $type, $id
  164. );
  165. // If the type value is null it is probably safe to assume we're eager loading
  166. // the relationship. In this case we'll just pass in a dummy query where we
  167. // need to remove any eager loads that may already be defined on a model.
  168. return empty($class = $this->{$type})
  169. ? $this->morphEagerTo($name, $type, $id, $ownerKey)
  170. : $this->morphInstanceTo($class, $name, $type, $id, $ownerKey);
  171. }
  172. /**
  173. * Define a polymorphic, inverse one-to-one or many relationship.
  174. *
  175. * @param string $name
  176. * @param string $type
  177. * @param string $id
  178. * @param string $ownerKey
  179. * @return \Illuminate\Database\Eloquent\Relations\MorphTo
  180. */
  181. protected function morphEagerTo($name, $type, $id, $ownerKey)
  182. {
  183. return $this->newMorphTo(
  184. $this->newQuery()->setEagerLoads([]), $this, $id, $ownerKey, $type, $name
  185. );
  186. }
  187. /**
  188. * Define a polymorphic, inverse one-to-one or many relationship.
  189. *
  190. * @param string $target
  191. * @param string $name
  192. * @param string $type
  193. * @param string $id
  194. * @param string $ownerKey
  195. * @return \Illuminate\Database\Eloquent\Relations\MorphTo
  196. */
  197. protected function morphInstanceTo($target, $name, $type, $id, $ownerKey)
  198. {
  199. $instance = $this->newRelatedInstance(
  200. static::getActualClassNameForMorph($target)
  201. );
  202. return $this->newMorphTo(
  203. $instance->newQuery(), $this, $id, $ownerKey ?? $instance->getKeyName(), $type, $name
  204. );
  205. }
  206. /**
  207. * Instantiate a new MorphTo relationship.
  208. *
  209. * @param \Illuminate\Database\Eloquent\Builder $query
  210. * @param \Illuminate\Database\Eloquent\Model $parent
  211. * @param string $foreignKey
  212. * @param string $ownerKey
  213. * @param string $type
  214. * @param string $relation
  215. * @return \Illuminate\Database\Eloquent\Relations\MorphTo
  216. */
  217. protected function newMorphTo(Builder $query, Model $parent, $foreignKey, $ownerKey, $type, $relation)
  218. {
  219. return new MorphTo($query, $parent, $foreignKey, $ownerKey, $type, $relation);
  220. }
  221. /**
  222. * Retrieve the actual class name for a given morph class.
  223. *
  224. * @param string $class
  225. * @return string
  226. */
  227. public static function getActualClassNameForMorph($class)
  228. {
  229. return Arr::get(Relation::morphMap() ?: [], $class, $class);
  230. }
  231. /**
  232. * Guess the "belongs to" relationship name.
  233. *
  234. * @return string
  235. */
  236. protected function guessBelongsToRelation()
  237. {
  238. list($one, $two, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
  239. return $caller['function'];
  240. }
  241. /**
  242. * Define a one-to-many relationship.
  243. *
  244. * @param string $related
  245. * @param string $foreignKey
  246. * @param string $localKey
  247. * @return \Illuminate\Database\Eloquent\Relations\HasMany
  248. */
  249. public function hasMany($related, $foreignKey = null, $localKey = null)
  250. {
  251. $instance = $this->newRelatedInstance($related);
  252. $foreignKey = $foreignKey ?: $this->getForeignKey();
  253. $localKey = $localKey ?: $this->getKeyName();
  254. return $this->newHasMany(
  255. $instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey
  256. );
  257. }
  258. /**
  259. * Instantiate a new HasMany relationship.
  260. *
  261. * @param \Illuminate\Database\Eloquent\Builder $query
  262. * @param \Illuminate\Database\Eloquent\Model $parent
  263. * @param string $foreignKey
  264. * @param string $localKey
  265. * @return \Illuminate\Database\Eloquent\Relations\HasMany
  266. */
  267. protected function newHasMany(Builder $query, Model $parent, $foreignKey, $localKey)
  268. {
  269. return new HasMany($query, $parent, $foreignKey, $localKey);
  270. }
  271. /**
  272. * Define a has-many-through relationship.
  273. *
  274. * @param string $related
  275. * @param string $through
  276. * @param string|null $firstKey
  277. * @param string|null $secondKey
  278. * @param string|null $localKey
  279. * @param string|null $secondLocalKey
  280. * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
  281. */
  282. public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null, $localKey = null, $secondLocalKey = null)
  283. {
  284. $through = new $through;
  285. $firstKey = $firstKey ?: $this->getForeignKey();
  286. $secondKey = $secondKey ?: $through->getForeignKey();
  287. return $this->newHasManyThrough(
  288. $this->newRelatedInstance($related)->newQuery(), $this, $through,
  289. $firstKey, $secondKey, $localKey ?: $this->getKeyName(),
  290. $secondLocalKey ?: $through->getKeyName()
  291. );
  292. }
  293. /**
  294. * Instantiate a new HasManyThrough relationship.
  295. *
  296. * @param \Illuminate\Database\Eloquent\Builder $query
  297. * @param \Illuminate\Database\Eloquent\Model $farParent
  298. * @param \Illuminate\Database\Eloquent\Model $throughParent
  299. * @param string $firstKey
  300. * @param string $secondKey
  301. * @param string $localKey
  302. * @param string $secondLocalKey
  303. * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
  304. */
  305. protected function newHasManyThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey)
  306. {
  307. return new HasManyThrough($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey);
  308. }
  309. /**
  310. * Define a polymorphic one-to-many relationship.
  311. *
  312. * @param string $related
  313. * @param string $name
  314. * @param string $type
  315. * @param string $id
  316. * @param string $localKey
  317. * @return \Illuminate\Database\Eloquent\Relations\MorphMany
  318. */
  319. public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
  320. {
  321. $instance = $this->newRelatedInstance($related);
  322. // Here we will gather up the morph type and ID for the relationship so that we
  323. // can properly query the intermediate table of a relation. Finally, we will
  324. // get the table and create the relationship instances for the developers.
  325. list($type, $id) = $this->getMorphs($name, $type, $id);
  326. $table = $instance->getTable();
  327. $localKey = $localKey ?: $this->getKeyName();
  328. return $this->newMorphMany($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
  329. }
  330. /**
  331. * Instantiate a new MorphMany relationship.
  332. *
  333. * @param \Illuminate\Database\Eloquent\Builder $query
  334. * @param \Illuminate\Database\Eloquent\Model $parent
  335. * @param string $type
  336. * @param string $id
  337. * @param string $localKey
  338. * @return \Illuminate\Database\Eloquent\Relations\MorphMany
  339. */
  340. protected function newMorphMany(Builder $query, Model $parent, $type, $id, $localKey)
  341. {
  342. return new MorphMany($query, $parent, $type, $id, $localKey);
  343. }
  344. /**
  345. * Define a many-to-many relationship.
  346. *
  347. * @param string $related
  348. * @param string $table
  349. * @param string $foreignPivotKey
  350. * @param string $relatedPivotKey
  351. * @param string $parentKey
  352. * @param string $relatedKey
  353. * @param string $relation
  354. * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
  355. */
  356. public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
  357. $parentKey = null, $relatedKey = null, $relation = null)
  358. {
  359. // If no relationship name was passed, we will pull backtraces to get the
  360. // name of the calling function. We will use that function name as the
  361. // title of this relation since that is a great convention to apply.
  362. if (is_null($relation)) {
  363. $relation = $this->guessBelongsToManyRelation();
  364. }
  365. // First, we'll need to determine the foreign key and "other key" for the
  366. // relationship. Once we have determined the keys we'll make the query
  367. // instances as well as the relationship instances we need for this.
  368. $instance = $this->newRelatedInstance($related);
  369. $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();
  370. $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();
  371. // If no table name was provided, we can guess it by concatenating the two
  372. // models using underscores in alphabetical order. The two model names
  373. // are transformed to snake case from their default CamelCase also.
  374. if (is_null($table)) {
  375. $table = $this->joiningTable($related);
  376. }
  377. return $this->newBelongsToMany(
  378. $instance->newQuery(), $this, $table, $foreignPivotKey,
  379. $relatedPivotKey, $parentKey ?: $this->getKeyName(),
  380. $relatedKey ?: $instance->getKeyName(), $relation
  381. );
  382. }
  383. /**
  384. * Instantiate a new BelongsToMany relationship.
  385. *
  386. * @param \Illuminate\Database\Eloquent\Builder $query
  387. * @param \Illuminate\Database\Eloquent\Model $parent
  388. * @param string $table
  389. * @param string $foreignPivotKey
  390. * @param string $relatedPivotKey
  391. * @param string $parentKey
  392. * @param string $relatedKey
  393. * @param string $relationName
  394. * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
  395. */
  396. protected function newBelongsToMany(Builder $query, Model $parent, $table, $foreignPivotKey, $relatedPivotKey,
  397. $parentKey, $relatedKey, $relationName = null)
  398. {
  399. return new BelongsToMany($query, $parent, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey, $relationName);
  400. }
  401. /**
  402. * Define a polymorphic many-to-many relationship.
  403. *
  404. * @param string $related
  405. * @param string $name
  406. * @param string $table
  407. * @param string $foreignPivotKey
  408. * @param string $relatedPivotKey
  409. * @param string $parentKey
  410. * @param string $relatedKey
  411. * @param bool $inverse
  412. * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
  413. */
  414. public function morphToMany($related, $name, $table = null, $foreignPivotKey = null,
  415. $relatedPivotKey = null, $parentKey = null,
  416. $relatedKey = null, $inverse = false)
  417. {
  418. $caller = $this->guessBelongsToManyRelation();
  419. // First, we will need to determine the foreign key and "other key" for the
  420. // relationship. Once we have determined the keys we will make the query
  421. // instances, as well as the relationship instances we need for these.
  422. $instance = $this->newRelatedInstance($related);
  423. $foreignPivotKey = $foreignPivotKey ?: $name.'_id';
  424. $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();
  425. // Now we're ready to create a new query builder for this related model and
  426. // the relationship instances for this relation. This relations will set
  427. // appropriate query constraints then entirely manages the hydrations.
  428. $table = $table ?: Str::plural($name);
  429. return $this->newMorphToMany(
  430. $instance->newQuery(), $this, $name, $table,
  431. $foreignPivotKey, $relatedPivotKey, $parentKey ?: $this->getKeyName(),
  432. $relatedKey ?: $instance->getKeyName(), $caller, $inverse
  433. );
  434. }
  435. /**
  436. * Instantiate a new HasManyThrough relationship.
  437. *
  438. * @param \Illuminate\Database\Eloquent\Builder $query
  439. * @param \Illuminate\Database\Eloquent\Model $parent
  440. * @param string $name
  441. * @param string $table
  442. * @param string $foreignPivotKey
  443. * @param string $relatedPivotKey
  444. * @param string $parentKey
  445. * @param string $relatedKey
  446. * @param string $relationName
  447. * @param bool $inverse
  448. * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
  449. */
  450. protected function newMorphToMany(Builder $query, Model $parent, $name, $table, $foreignPivotKey,
  451. $relatedPivotKey, $parentKey, $relatedKey,
  452. $relationName = null, $inverse = false)
  453. {
  454. return new MorphToMany($query, $parent, $name, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey,
  455. $relationName, $inverse);
  456. }
  457. /**
  458. * Define a polymorphic, inverse many-to-many relationship.
  459. *
  460. * @param string $related
  461. * @param string $name
  462. * @param string $table
  463. * @param string $foreignPivotKey
  464. * @param string $relatedPivotKey
  465. * @param string $parentKey
  466. * @param string $relatedKey
  467. * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
  468. */
  469. public function morphedByMany($related, $name, $table = null, $foreignPivotKey = null,
  470. $relatedPivotKey = null, $parentKey = null, $relatedKey = null)
  471. {
  472. $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();
  473. // For the inverse of the polymorphic many-to-many relations, we will change
  474. // the way we determine the foreign and other keys, as it is the opposite
  475. // of the morph-to-many method since we're figuring out these inverses.
  476. $relatedPivotKey = $relatedPivotKey ?: $name.'_id';
  477. return $this->morphToMany(
  478. $related, $name, $table, $foreignPivotKey,
  479. $relatedPivotKey, $parentKey, $relatedKey, true
  480. );
  481. }
  482. /**
  483. * Get the relationship name of the belongs to many.
  484. *
  485. * @return string
  486. */
  487. protected function guessBelongsToManyRelation()
  488. {
  489. $caller = Arr::first(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), function ($trace) {
  490. return ! in_array($trace['function'], Model::$manyMethods);
  491. });
  492. return ! is_null($caller) ? $caller['function'] : null;
  493. }
  494. /**
  495. * Get the joining table name for a many-to-many relation.
  496. *
  497. * @param string $related
  498. * @return string
  499. */
  500. public function joiningTable($related)
  501. {
  502. // The joining table name, by convention, is simply the snake cased models
  503. // sorted alphabetically and concatenated with an underscore, so we can
  504. // just sort the models and join them together to get the table name.
  505. $models = [
  506. Str::snake(class_basename($related)),
  507. Str::snake(class_basename($this)),
  508. ];
  509. // Now that we have the model names in an array we can just sort them and
  510. // use the implode function to join them together with an underscores,
  511. // which is typically used by convention within the database system.
  512. sort($models);
  513. return strtolower(implode('_', $models));
  514. }
  515. /**
  516. * Determine if the model touches a given relation.
  517. *
  518. * @param string $relation
  519. * @return bool
  520. */
  521. public function touches($relation)
  522. {
  523. return in_array($relation, $this->touches);
  524. }
  525. /**
  526. * Touch the owning relations of the model.
  527. *
  528. * @return void
  529. */
  530. public function touchOwners()
  531. {
  532. foreach ($this->touches as $relation) {
  533. $this->$relation()->touch();
  534. if ($this->$relation instanceof self) {
  535. $this->$relation->fireModelEvent('saved', false);
  536. $this->$relation->touchOwners();
  537. } elseif ($this->$relation instanceof Collection) {
  538. $this->$relation->each(function (Model $relation) {
  539. $relation->touchOwners();
  540. });
  541. }
  542. }
  543. }
  544. /**
  545. * Get the polymorphic relationship columns.
  546. *
  547. * @param string $name
  548. * @param string $type
  549. * @param string $id
  550. * @return array
  551. */
  552. protected function getMorphs($name, $type, $id)
  553. {
  554. return [$type ?: $name.'_type', $id ?: $name.'_id'];
  555. }
  556. /**
  557. * Get the class name for polymorphic relations.
  558. *
  559. * @return string
  560. */
  561. public function getMorphClass()
  562. {
  563. $morphMap = Relation::morphMap();
  564. if (! empty($morphMap) && in_array(static::class, $morphMap)) {
  565. return array_search(static::class, $morphMap, true);
  566. }
  567. return static::class;
  568. }
  569. /**
  570. * Create a new model instance for a related model.
  571. *
  572. * @param string $class
  573. * @return mixed
  574. */
  575. protected function newRelatedInstance($class)
  576. {
  577. return tap(new $class, function ($instance) {
  578. if (! $instance->getConnectionName()) {
  579. $instance->setConnection($this->connection);
  580. }
  581. });
  582. }
  583. /**
  584. * Get all the loaded relations for the instance.
  585. *
  586. * @return array
  587. */
  588. public function getRelations()
  589. {
  590. return $this->relations;
  591. }
  592. /**
  593. * Get a specified relationship.
  594. *
  595. * @param string $relation
  596. * @return mixed
  597. */
  598. public function getRelation($relation)
  599. {
  600. return $this->relations[$relation];
  601. }
  602. /**
  603. * Determine if the given relation is loaded.
  604. *
  605. * @param string $key
  606. * @return bool
  607. */
  608. public function relationLoaded($key)
  609. {
  610. return array_key_exists($key, $this->relations);
  611. }
  612. /**
  613. * Set the given relationship on the model.
  614. *
  615. * @param string $relation
  616. * @param mixed $value
  617. * @return $this
  618. */
  619. public function setRelation($relation, $value)
  620. {
  621. $this->relations[$relation] = $value;
  622. return $this;
  623. }
  624. /**
  625. * Unset a loaded relationship.
  626. *
  627. * @param string $relation
  628. * @return $this
  629. */
  630. public function unsetRelation($relation)
  631. {
  632. unset($this->relations[$relation]);
  633. return $this;
  634. }
  635. /**
  636. * Set the entire relations array on the model.
  637. *
  638. * @param array $relations
  639. * @return $this
  640. */
  641. public function setRelations(array $relations)
  642. {
  643. $this->relations = $relations;
  644. return $this;
  645. }
  646. /**
  647. * Get the relationships that are touched on save.
  648. *
  649. * @return array
  650. */
  651. public function getTouchedRelations()
  652. {
  653. return $this->touches;
  654. }
  655. /**
  656. * Set the relationships that are touched on save.
  657. *
  658. * @param array $touches
  659. * @return $this
  660. */
  661. public function setTouchedRelations(array $touches)
  662. {
  663. $this->touches = $touches;
  664. return $this;
  665. }
  666. }