DatabaseEloquentRelationshipsTest.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <?php
  2. namespace Illuminate\Tests\Database\EloquentRelationshipsTest;
  3. use Illuminate\Database\Eloquent\Builder;
  4. use Illuminate\Database\Eloquent\Model;
  5. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  6. use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  7. use Illuminate\Database\Eloquent\Relations\HasMany;
  8. use Illuminate\Database\Eloquent\Relations\HasManyThrough;
  9. use Illuminate\Database\Eloquent\Relations\HasOne;
  10. use Illuminate\Database\Eloquent\Relations\HasOneThrough;
  11. use Illuminate\Database\Eloquent\Relations\MorphMany;
  12. use Illuminate\Database\Eloquent\Relations\MorphOne;
  13. use Illuminate\Database\Eloquent\Relations\MorphTo;
  14. use Illuminate\Database\Eloquent\Relations\MorphToMany;
  15. use PHPUnit\Framework\TestCase;
  16. class DatabaseEloquentRelationshipsTest extends TestCase
  17. {
  18. public function testStandardRelationships()
  19. {
  20. $post = new Post;
  21. $this->assertInstanceOf(HasOne::class, $post->attachment());
  22. $this->assertInstanceOf(BelongsTo::class, $post->author());
  23. $this->assertInstanceOf(HasMany::class, $post->comments());
  24. $this->assertInstanceOf(MorphOne::class, $post->owner());
  25. $this->assertInstanceOf(MorphMany::class, $post->likes());
  26. $this->assertInstanceOf(BelongsToMany::class, $post->viewers());
  27. $this->assertInstanceOf(HasManyThrough::class, $post->lovers());
  28. $this->assertInstanceOf(HasOneThrough::class, $post->contract());
  29. $this->assertInstanceOf(MorphToMany::class, $post->tags());
  30. $this->assertInstanceOf(MorphTo::class, $post->postable());
  31. }
  32. public function testOverriddenRelationships()
  33. {
  34. $post = new CustomPost;
  35. $this->assertInstanceOf(CustomHasOne::class, $post->attachment());
  36. $this->assertInstanceOf(CustomBelongsTo::class, $post->author());
  37. $this->assertInstanceOf(CustomHasMany::class, $post->comments());
  38. $this->assertInstanceOf(CustomMorphOne::class, $post->owner());
  39. $this->assertInstanceOf(CustomMorphMany::class, $post->likes());
  40. $this->assertInstanceOf(CustomBelongsToMany::class, $post->viewers());
  41. $this->assertInstanceOf(CustomHasManyThrough::class, $post->lovers());
  42. $this->assertInstanceOf(CustomHasOneThrough::class, $post->contract());
  43. $this->assertInstanceOf(CustomMorphToMany::class, $post->tags());
  44. $this->assertInstanceOf(CustomMorphTo::class, $post->postable());
  45. }
  46. public function testAlwaysUnsetBelongsToRelationWhenReceivedModelId()
  47. {
  48. // create users
  49. $user1 = (new FakeRelationship)->forceFill(['id' => 1]);
  50. $user2 = (new FakeRelationship)->forceFill(['id' => 2]);
  51. // sync user 1 using Model
  52. $post = new Post;
  53. $post->author()->associate($user1);
  54. $post->syncOriginal();
  55. // associate user 2 using Model
  56. $post->author()->associate($user2);
  57. $this->assertTrue($post->isDirty());
  58. $this->assertTrue($post->relationLoaded('author'));
  59. $this->assertSame($user2, $post->author);
  60. // associate user 1 using model ID
  61. $post->author()->associate($user1->id);
  62. $this->assertTrue($post->isClean());
  63. // we must unset relation even if attributes are clean
  64. $this->assertFalse($post->relationLoaded('author'));
  65. }
  66. }
  67. class FakeRelationship extends Model
  68. {
  69. //
  70. }
  71. class Post extends Model
  72. {
  73. public function attachment()
  74. {
  75. return $this->hasOne(FakeRelationship::class);
  76. }
  77. public function author()
  78. {
  79. return $this->belongsTo(FakeRelationship::class);
  80. }
  81. public function comments()
  82. {
  83. return $this->hasMany(FakeRelationship::class);
  84. }
  85. public function likes()
  86. {
  87. return $this->morphMany(FakeRelationship::class, 'actionable');
  88. }
  89. public function owner()
  90. {
  91. return $this->morphOne(FakeRelationship::class, 'property');
  92. }
  93. public function viewers()
  94. {
  95. return $this->belongsToMany(FakeRelationship::class);
  96. }
  97. public function lovers()
  98. {
  99. return $this->hasManyThrough(FakeRelationship::class, FakeRelationship::class);
  100. }
  101. public function contract()
  102. {
  103. return $this->hasOneThrough(FakeRelationship::class, FakeRelationship::class);
  104. }
  105. public function tags()
  106. {
  107. return $this->morphToMany(FakeRelationship::class, 'taggable');
  108. }
  109. public function postable()
  110. {
  111. return $this->morphTo();
  112. }
  113. }
  114. class CustomPost extends Post
  115. {
  116. protected function newBelongsTo(Builder $query, Model $child, $foreignKey, $ownerKey, $relation)
  117. {
  118. return new CustomBelongsTo($query, $child, $foreignKey, $ownerKey, $relation);
  119. }
  120. protected function newHasMany(Builder $query, Model $parent, $foreignKey, $localKey)
  121. {
  122. return new CustomHasMany($query, $parent, $foreignKey, $localKey);
  123. }
  124. protected function newHasOne(Builder $query, Model $parent, $foreignKey, $localKey)
  125. {
  126. return new CustomHasOne($query, $parent, $foreignKey, $localKey);
  127. }
  128. protected function newMorphOne(Builder $query, Model $parent, $type, $id, $localKey)
  129. {
  130. return new CustomMorphOne($query, $parent, $type, $id, $localKey);
  131. }
  132. protected function newMorphMany(Builder $query, Model $parent, $type, $id, $localKey)
  133. {
  134. return new CustomMorphMany($query, $parent, $type, $id, $localKey);
  135. }
  136. protected function newBelongsToMany(Builder $query, Model $parent, $table, $foreignPivotKey, $relatedPivotKey,
  137. $parentKey, $relatedKey, $relationName = null
  138. ) {
  139. return new CustomBelongsToMany($query, $parent, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey, $relationName);
  140. }
  141. protected function newHasManyThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey,
  142. $secondKey, $localKey, $secondLocalKey
  143. ) {
  144. return new CustomHasManyThrough($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey);
  145. }
  146. protected function newHasOneThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey,
  147. $secondKey, $localKey, $secondLocalKey
  148. ) {
  149. return new CustomHasOneThrough($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey);
  150. }
  151. protected function newMorphToMany(Builder $query, Model $parent, $name, $table, $foreignPivotKey,
  152. $relatedPivotKey, $parentKey, $relatedKey, $relationName = null, $inverse = false)
  153. {
  154. return new CustomMorphToMany($query, $parent, $name, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey,
  155. $relationName, $inverse);
  156. }
  157. protected function newMorphTo(Builder $query, Model $parent, $foreignKey, $ownerKey, $type, $relation)
  158. {
  159. return new CustomMorphTo($query, $parent, $foreignKey, $ownerKey, $type, $relation);
  160. }
  161. }
  162. class CustomHasOne extends HasOne
  163. {
  164. //
  165. }
  166. class CustomBelongsTo extends BelongsTo
  167. {
  168. //
  169. }
  170. class CustomHasMany extends HasMany
  171. {
  172. //
  173. }
  174. class CustomMorphOne extends MorphOne
  175. {
  176. //
  177. }
  178. class CustomMorphMany extends MorphMany
  179. {
  180. //
  181. }
  182. class CustomBelongsToMany extends BelongsToMany
  183. {
  184. //
  185. }
  186. class CustomHasManyThrough extends HasManyThrough
  187. {
  188. //
  189. }
  190. class CustomHasOneThrough extends HasOneThrough
  191. {
  192. //
  193. }
  194. class CustomMorphToMany extends MorphToMany
  195. {
  196. //
  197. }
  198. class CustomMorphTo extends MorphTo
  199. {
  200. //
  201. }