結論
Eagerロードで読み込んだリレーションは、unset
することで削除することができます。
やりたかったこと
背景なども記載しておきます。
レスポンスはjson形式を想定しています。
リレーションデータと一緒にEloquentのコレクションを取得し、取得したデータのリレーションデータを処理。そのままEloquentのコレクションを返した場合、リレーションデータも一緒に返ります。すでに、リレーションデータを処理したのでリレーションデータを返す必要はありませんでした。
コードで表すとこんな感じです。
Models/Post.php
class Post extends Model
{
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}
}
PostController.php
// リレーションデータと一緒にEloquentのコレクションを取得
$posts = Post::with('comments')->get();
foreach ($posts as $post) {
// 取得したデータのリレーションデータを処理
$comments_count = $post->comments->count();
$post->comments_count = $comments_count;
// リレーションデータの削除
unset($post->comments);
}
return $posts;
null
を代入ではリレーションは削除することができませんでした。
Laravelの実装の確認
unset
することでリレーションデータも削除されます。
framework/src/Illuminate/Database/Eloquent/Model.php
public function __unset($key)
{
$this->offsetUnset($key);
}
public function offsetUnset($offset): void
{
unset($this->attributes[$offset], $this->relations[$offset]);
}
offsetUnset
関数
https://github.com/laravel/framework/blob/v11.27.2/src/Illuminate/Database/Eloquent/Model.php#L2318-L2321
$post->offsetUnset('comments');
でも同じ結果になりますね。
なぜnull代入ではだめだったのか
実装を確認します。
framework/src/Illuminate/Database/Eloquent/Model.php
public function __set($key, $value)
{
$this->setAttribute($key, $value);
}
null
を代入した場合、__set
関数が実行されます。内部的にはsetAttribute
関数が実行されるだけなので、relations
が消えないためでした。
[AD]