@@ -39,6 +39,9 @@ protected function initRelations(): void
39
39
helper ('inflector ' );
40
40
}
41
41
42
+ /**
43
+ * Set the relation to use.
44
+ */
42
45
public function with (string $ relation , ?Closure $ closure = null ): static
43
46
{
44
47
if (str_contains ($ relation , '. ' )) {
@@ -64,6 +67,9 @@ public function with(string $relation, ?Closure $closure = null): static
64
67
return $ this ;
65
68
}
66
69
70
+ /**
71
+ * Validate relation definition.
72
+ */
67
73
private function checkReturnType (string $ methodName ): bool
68
74
{
69
75
if (! method_exists ($ this , $ methodName )) {
@@ -183,12 +189,18 @@ public function belongsToMany(Model|string $model, ?string $pivotTable = null, ?
183
189
->setMany ($ pivotTable , $ pivotForeignKey , $ pivotRelatedKey );
184
190
}
185
191
192
+ /**
193
+ * Return model instance.
194
+ */
186
195
private function getModelInstance (Model |string $ model ): Model
187
196
{
188
197
return $ model instanceof Model ? $ model : model ($ model );
189
198
}
190
199
191
- private function createPivotTableName ($ table1 , $ table2 ): string
200
+ /**
201
+ * Create pivot table name.
202
+ */
203
+ private function createPivotTableName (mixed $ table1 , mixed $ table2 ): string
192
204
{
193
205
$ tables = [$ table1 , $ table2 ];
194
206
sort ($ tables );
@@ -199,6 +211,8 @@ private function createPivotTableName($table1, $table2): string
199
211
}
200
212
201
213
/**
214
+ * Get the caller method name.
215
+ *
202
216
* @throws ReflectionException
203
217
*/
204
218
private function getInitialMethodName (): string
@@ -378,6 +392,9 @@ protected function relationsAfterFind(array $eventData): array
378
392
return $ eventData ;
379
393
}
380
394
395
+ /**
396
+ * Get relation data for a single item.
397
+ */
381
398
protected function getDataForRelationById (int |string $ id , Relation $ relation )
382
399
{
383
400
$ relation ->applyWith ()->applyRelation ([$ id ], $ this ->primaryKey )->applyConditions ();
@@ -389,6 +406,9 @@ protected function getDataForRelationById(int|string $id, Relation $relation)
389
406
return $ relation ->filterResults ($ results , $ this ->tempReturnType );
390
407
}
391
408
409
+ /**
410
+ * Get relation data for many items.
411
+ */
392
412
protected function getDataForRelationByIds (array $ id , Relation $ relation ): array
393
413
{
394
414
$ relation ->applyWith ()->applyRelation ($ id , $ this ->primaryKey )->applyConditions ();
@@ -439,6 +459,28 @@ protected function getDataForRelationByIds(array $id, Relation $relation): array
439
459
return $ relationData ;
440
460
}
441
461
462
+ /**
463
+ * Validate if given relation can be handled during write operation.
464
+ */
465
+ protected function validateWriteRelations (): void
466
+ {
467
+ if ($ this ->relations === []) {
468
+ return ;
469
+ }
470
+
471
+ foreach ($ this ->relations as $ relation ) {
472
+ if (
473
+ ! in_array ($ relation ->type , [RelationTypes::hasOne, RelationTypes::hasMany], true )
474
+ || (
475
+ in_array ($ relation ->type , [RelationTypes::hasOne, RelationTypes::hasMany], true )
476
+ && ($ relation ->hasMany () || $ relation ->hasThrough ())
477
+ )
478
+ ) {
479
+ throw NestedModelException::forRelationDoesNotSupportWrite ();
480
+ }
481
+ }
482
+ }
483
+
442
484
/**
443
485
* Whether to use transaction during insert/update.
444
486
*/
@@ -451,6 +493,8 @@ public function useTransactions(bool $value = true): static
451
493
452
494
public function insert ($ row = null , bool $ returnID = true ): bool |int |string
453
495
{
496
+ $ this ->validateWriteRelations ();
497
+
454
498
if ($ this ->useTransactions ) {
455
499
try {
456
500
$ this ->db ->transException (true )->transStart ();
@@ -480,6 +524,8 @@ public function insert($row = null, bool $returnID = true): bool|int|string
480
524
481
525
public function update ($ id = null , $ row = null ): bool
482
526
{
527
+ $ this ->validateWriteRelations ();
528
+
483
529
if ($ this ->useTransactions ) {
484
530
try {
485
531
$ this ->db ->transException (true )->transStart ();
0 commit comments