Search code examples
phplaraveleloquenthydration

How I can Hydrate a Laravel Model with its children when I create Both of them?


In a laravel project I do:

$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);

And I have a resource where I serialize my 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)
        ];
    }
}

And one for the child:

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,
        ];
    }
}

As you can see I create both a model with child elements in one go then I create a resource. The MyModel model is:

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');
    }
}

And simiraly is ModelChild one:

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');
    }
}

My question is how I can hydrate the model in $model with $modelChildValues so I can avoid selecting for inserted models?


Solution

  • You can use methods like setRelation to manually attach one or more models

    $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);