В проекте laravel я делаю:
$childValues = [1,3,4,5];
$model = MyModel::create(['value'=>1.2]);
$modelChildValues=[];
foreach($childValues as $value){
$modelChildValues[]=ModelChild::create(['parent_id'=>$model->id,'value'=>$value]);
}
$reource = new MyModelResource($model);
И у меня есть ресурс, где я сериализую свою модель:
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class MyModelResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'value'=>$this->value,
'children' => ModelChildResource::collection($this->children)
];
}
}
И еще один для ребенка:
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ModelChildResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'value'=>$this->value,
];
}
}
Как видите, я создаю модель с дочерними элементами за один раз, а затем создаю ресурс. Модель MyModel
:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
use HasFactory;
protected function children()
{
return $this->hasMany(ModelChild::class,'child_id','id');
}
}
И симирали ModelChild
один:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
use HasFactory;
protected function mymodel()
{
return $this->belongsTo(Model::class,'id','child_id');
}
}
Мой вопрос: как я могу увлажнить модель в $model
с помощью $modelChildValues
, чтобы избежать выбора вставленных моделей?
Вы можете использовать такие методы, как setRelation
, чтобы вручную прикрепить одну или несколько моделей.
$childValues = [1,3,4,5];
$model = MyModel::create(['value'=>1.2]);
$children = collect([]);
foreach($childValues as $value) {
// the relation field will be auto filled
$children->push($model->children()->create(['value' => $value]));
}
$model->setRelation('children', $children);
$reource = new MyModelResource($model);
Но не будет ли $model->children()->create(['value' => $value])
автоматически создаваться дочерний элемент модели??? Почему setRelation
тоже требуется?
@DimitriosDesyllas нет, create выполняет запрос на вставку в вашу БД и возвращает созданную модель. Теперь ваша модель загружена в память и вы можете решить, что с ней делать. Имейте в виду, что у $model
может быть больше дочерних элементов, чем те, которые вы создали в этом методе, и таким образом вы присоединяете только те, которые вы создали во время этого конкретного вызова метода.
Когда вы звоните
$model->children()->create()
, вам не нужен'parent_id' => $model->id
; это подразумевается через$model->children()
. Затем вы можете просто вызвать$model->load('children')
(или$model->load(['children' => function ($query) use ($childValues) { return $query->whereIn('value', $childValues); }]);
, чтобы загрузить только те, которые вы создали). Кажется, вы пытаетесь избежать одного дополнительного запроса для загрузки этих записей из БД, что на самом деле не является узким местом в производительности...->create()
возвращает экземпляр, но не назначает его автоматически$model->children
; вам нужно это сделать.