22
33namespace MongoDB \Laravel \Eloquent ;
44
5+ use Illuminate \Database \Eloquent \Concerns \HasRelationships ;
56use Illuminate \Database \Eloquent \Model as EloquentModel ;
67use Illuminate \Database \Eloquent \Relations \MorphOne ;
78use Illuminate \Support \Str ;
@@ -24,14 +25,16 @@ trait HybridRelations
2425 * Define a one-to-one relationship.
2526 *
2627 * @param class-string<EloquentModel> $related
27- * @param string $foreignKey
28- * @param string $localKey
28+ * @param string|null $foreignKey
29+ * @param string|null $localKey
2930 * @return \Illuminate\Database\Eloquent\Relations\HasOne
31+ *
32+ * @see HasRelationships::hasOne()
3033 */
3134 public function hasOne ($ related , $ foreignKey = null , $ localKey = null )
3235 {
3336 // Check if it is a relation with an original model.
34- if (! is_subclass_of ($ related, MongoDBModel::class )) {
37+ if (! self :: isMongoDBModel ($ related )) {
3538 return parent ::hasOne ($ related , $ foreignKey , $ localKey );
3639 }
3740
@@ -57,7 +60,7 @@ public function hasOne($related, $foreignKey = null, $localKey = null)
5760 public function morphOne ($ related , $ name , $ type = null , $ id = null , $ localKey = null )
5861 {
5962 // Check if it is a relation with an original model.
60- if (! is_subclass_of ($ related, MongoDBModel::class )) {
63+ if (! self :: isMongoDBModel ($ related )) {
6164 return parent ::morphOne ($ related , $ name , $ type , $ id , $ localKey );
6265 }
6366
@@ -74,24 +77,24 @@ public function morphOne($related, $name, $type = null, $id = null, $localKey =
7477 * Define a one-to-many relationship.
7578 *
7679 * @param class-string<EloquentModel> $related
77- * @param string $foreignKey
80+ * @param string $foreignPivotKey
7881 * @param string $localKey
7982 * @return \Illuminate\Database\Eloquent\Relations\HasMany
8083 */
81- public function hasMany ($ related , $ foreignKey = null , $ localKey = null )
84+ public function hasMany ($ related , $ foreignPivotKey = null , $ localKey = null )
8285 {
8386 // Check if it is a relation with an original model.
84- if (! is_subclass_of ($ related, MongoDBModel::class )) {
85- return parent ::hasMany ($ related , $ foreignKey , $ localKey );
87+ if (! self :: isMongoDBModel ($ related )) {
88+ return parent ::hasMany ($ related , $ foreignPivotKey , $ localKey );
8689 }
8790
88- $ foreignKey = $ foreignKey ?: $ this ->getForeignKey ();
91+ $ foreignPivotKey = $ foreignPivotKey ?: $ this ->getForeignKey ();
8992
9093 $ instance = new $ related ;
9194
9295 $ localKey = $ localKey ?: $ this ->getKeyName ();
9396
94- return new HasMany ($ instance ->newQuery (), $ this , $ foreignKey , $ localKey );
97+ return new HasMany ($ instance ->newQuery (), $ this , $ foreignPivotKey , $ localKey );
9598 }
9699
97100 /**
@@ -103,11 +106,13 @@ public function hasMany($related, $foreignKey = null, $localKey = null)
103106 * @param string $id
104107 * @param string $localKey
105108 * @return \Illuminate\Database\Eloquent\Relations\MorphMany
109+ *
110+ * @see HasRelationships::morphMany()
106111 */
107112 public function morphMany ($ related , $ name , $ type = null , $ id = null , $ localKey = null )
108113 {
109114 // Check if it is a relation with an original model.
110- if (! is_subclass_of ($ related, MongoDBModel::class )) {
115+ if (! self :: isMongoDBModel ($ related )) {
111116 return parent ::morphMany ($ related , $ name , $ type , $ id , $ localKey );
112117 }
113118
@@ -129,12 +134,14 @@ public function morphMany($related, $name, $type = null, $id = null, $localKey =
129134 * Define an inverse one-to-one or many relationship.
130135 *
131136 * @param class-string<EloquentModel> $related
132- * @param string $foreignKey
133- * @param string $otherKey
137+ * @param string $foreignPivotKey
138+ * @param string $relatedPivotKey
134139 * @param string $relation
135140 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
141+ *
142+ * @see HasRelationships::belongsTo()
136143 */
137- public function belongsTo ($ related , $ foreignKey = null , $ otherKey = null , $ relation = null )
144+ public function belongsTo ($ related , $ foreignPivotKey = null , $ relatedPivotKey = null , $ relation = null )
138145 {
139146 // If no relation name was given, we will use this debug backtrace to extract
140147 // the calling method's name and use that as the relationship name as most
@@ -144,15 +151,15 @@ public function belongsTo($related, $foreignKey = null, $otherKey = null, $relat
144151 }
145152
146153 // Check if it is a relation with an original model.
147- if (! is_subclass_of ($ related, MongoDBModel::class )) {
148- return parent ::belongsTo ($ related , $ foreignKey , $ otherKey , $ relation );
154+ if (! self :: isMongoDBModel ($ related )) {
155+ return parent ::belongsTo ($ related , $ foreignPivotKey , $ relatedPivotKey , $ relation );
149156 }
150157
151158 // If no foreign key was supplied, we can use a backtrace to guess the proper
152159 // foreign key name by using the name of the relationship function, which
153160 // when combined with an "_id" should conventionally match the columns.
154- if ($ foreignKey === null ) {
155- $ foreignKey = Str::snake ($ relation ).'_id ' ;
161+ if ($ foreignPivotKey === null ) {
162+ $ foreignPivotKey = Str::snake ($ relation ).'_id ' ;
156163 }
157164
158165 $ instance = new $ related ;
@@ -162,9 +169,9 @@ public function belongsTo($related, $foreignKey = null, $otherKey = null, $relat
162169 // actually be responsible for retrieving and hydrating every relations.
163170 $ query = $ instance ->newQuery ();
164171
165- $ otherKey = $ otherKey ?: $ instance ->getKeyName ();
172+ $ relatedPivotKey = $ relatedPivotKey ?: $ instance ->getKeyName ();
166173
167- return new BelongsTo ($ query , $ this , $ foreignKey , $ otherKey , $ relation );
174+ return new BelongsTo ($ query , $ this , $ foreignPivotKey , $ relatedPivotKey , $ relation );
168175 }
169176
170177 /**
@@ -175,6 +182,8 @@ public function belongsTo($related, $foreignKey = null, $otherKey = null, $relat
175182 * @param string $id
176183 * @param string $ownerKey
177184 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
185+ *
186+ * @see HasRelationships::morphTo()
178187 */
179188 public function morphTo ($ name = null , $ type = null , $ id = null , $ ownerKey = null )
180189 {
@@ -214,23 +223,20 @@ public function morphTo($name = null, $type = null, $id = null, $ownerKey = null
214223 * Define a many-to-many relationship.
215224 *
216225 * @param class-string<EloquentModel> $related
217- * @param string|null $collection
218- * @param string|null $foreignKey
219- * @param string|null $otherKey
220- * @param string|null $parentKey
221- * @param string|null $relatedKey
222- * @param string|null $relation
226+ * @param string|null $collection
227+ * @param string|null $foreignPivotKey
228+ * @param string|null $relatedPivotKey
229+ * @param string|null $parentKey
230+ * @param string|null $relatedKey
231+ * @param string|null $relation
223232 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
233+ *
234+ * @see HasRelationships::belongsToMany()
224235 */
225- public function belongsToMany (
226- $ related ,
227- $ collection = null ,
228- $ foreignKey = null ,
229- $ otherKey = null ,
230- $ parentKey = null ,
231- $ relatedKey = null ,
232- $ relation = null
233- ) {
236+ public function belongsToMany ($ related , $ collection = null , $ foreignPivotKey = null , $ relatedPivotKey = null ,
237+ $ parentKey = null , $ relatedKey = null , $ relation = null )
238+ {
239+
234240 // If no relationship name was passed, we will pull backtraces to get the
235241 // name of the calling function. We will use that function name as the
236242 // title of this relation since that is a great convention to apply.
@@ -239,12 +245,12 @@ public function belongsToMany(
239245 }
240246
241247 // Check if it is a relation with an original model.
242- if (! is_subclass_of ($ related, MongoDBModel::class )) {
248+ if (! self :: isMongoDBModel ($ related )) {
243249 return parent ::belongsToMany (
244250 $ related ,
245251 $ collection ,
246- $ foreignKey ,
247- $ otherKey ,
252+ $ foreignPivotKey ,
253+ $ relatedPivotKey ,
248254 $ parentKey ,
249255 $ relatedKey ,
250256 $ relation
@@ -255,11 +261,15 @@ public function belongsToMany(
255261 // First, we'll need to determine the foreign key and "other key" for the
256262 // relationship. Once we have determined the keys we'll make the query
257263 // instances as well as the relationship instances we need for this.
258- $ foreignKey = $ foreignKey ?: $ this ->getForeignKey ().'s ' ;
264+ $ foreignPivotKey = $ foreignPivotKey ?: $ this ->getForeignKey ().'s ' ;
259265
260266 $ instance = new $ related ;
261267
262- $ otherKey = $ otherKey ?: $ instance ->getForeignKey ().'s ' ;
268+ if ($ relatedPivotKey === $ relation ) {
269+ throw new \LogicException (sprintf ('In %s::%s(), the key cannot be identical to the relation name "%s". The default key is "%s". ' , static ::class, $ relation , $ relation , $ instance ->getForeignKey () . 's ' ));
270+ }
271+
272+ $ relatedPivotKey = $ relatedPivotKey ?: $ instance ->getForeignKey ().'s ' ;
263273
264274 // If no table name was provided, we can guess it by concatenating the two
265275 // models using underscores in alphabetical order. The two model names
@@ -277,8 +287,8 @@ public function belongsToMany(
277287 $ query ,
278288 $ this ,
279289 $ collection ,
280- $ foreignKey ,
281- $ otherKey ,
290+ $ foreignPivotKey ,
291+ $ relatedPivotKey ,
282292 $ parentKey ?: $ this ->getKeyName (),
283293 $ relatedKey ?: $ instance ->getKeyName (),
284294 $ relation
@@ -304,10 +314,19 @@ protected function guessBelongsToManyRelation()
304314 */
305315 public function newEloquentBuilder ($ query )
306316 {
307- if (is_subclass_of ( $ this , MongoDBModel ::class)) {
317+ if (self :: isMongoDBModel ( static ::class)) {
308318 return new Builder ($ query );
309319 }
310320
311321 return new EloquentBuilder ($ query );
312322 }
323+
324+ /**
325+ * @param class-string<EloquentModel> $model
326+ * @return bool
327+ */
328+ final protected static function isMongoDBModel (string $ model ): bool
329+ {
330+ return is_subclass_of ($ model , MongoDBModel::class);
331+ }
313332}
0 commit comments