Hello,
i have a user and setting model, in my case a user and setting have a 1:1 relation.
For each model there is a CRUD API endpoint, e.g. for better understanding /api/users and /api/users/{user}/settings
This endpoints returns a JsonResource. The user resource includes the setting resource on index and show GET request. (See code snippets below)
The problem i figured out was, that i trigger the n+1 problem in the SettingResource with $this->user->id. If i replace this with the foreign key $this->user_id everything is working fine and i have no n+1 problem.
Sound's logically and for now i have fixed my problem. But i want to understand how can i avoid this n+1 Problem in this $this->user->* case? Maybe in a next feature the SettingResource should return the user's email and $this->user->email triggers the error again.
maybe someone can help me
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'email' => $this->email,
'locale' => $this->locale,
'settings' => $this->whenLoaded('setting', SettingResource::make($this->setting)),
];
}
}
class SettingResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'user_id' => $this->user->id,
'foo' => 'bar',
}
}
class User extends Model
{
protected $with = [
'setting',
];
public function setting(): HasOne
{
return $this->hasOne(Setting::class)->withDefault();
}
}
class Setting extends Model
{
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
/** parts of the migration */
Schema::create('settings', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->uuid('user_id');
// some other fields
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
$table->timestamps();
});
Schema::create('users', function (Blueprint $table) {
$table->uuid('id')->primary();
// some other fields
$table->timestamps();
$table->softDeletes();
});
public function index(): ResourceCollection
{
return UserResource::collection(
User::query()->paginate($user)
);
}