Laravel:使用 belongsTo() 向我的模型添加意外属性

Laravel: Using belongsTo() add unexpected attributes to my Model

我正在使用 Lumen 编写 REST API。我的示例有 2 个模型 UserPostPost 模型使用方法 belongsTo 获取创建此 post 的 User 模型。我的目标是定义一个 accessor,这样我就可以像 Post::find($id)->author 一样获得 post 的作者用户名。所以根据文档我这样做:

Post.php :

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  protected $table = 'posts';
  protected $appends = ['author'];

  protected $fillable = [
    'title',
    'description'
  ];

  protected $hidden = [
    'user_id',
    'created_at',
    'updated_at'
  ];

  public function user()
  {
    return $this->belongsTo('App\User', 'user_id');
  }

  public function getAuthorAttribute()
  {
    return $this->user->username;
  }
}

现在 getter 运行良好,我可以轻松获得给定 Post 的作者。

但是,如果我尝试在 JSON 响应中 return Post,它也会 return 我奇怪的属性,如 user 似乎来了从我的 user() 方法调用 belongsTo():

return response()->json(Post::find(2), 200);
{
    "id": 2,
    "title": "Amazing Post",
    "description": "Nice post",
    "author": "FooBar",
    "user": {
        "id": 4,
        "username": "FooBar"
    }
}

如果我使用 attributesToArray() 它会按预期工作:

return response()->json(Post::find(2)->attributesToArray(), 200);
{
    "id": 2,
    "title": "Amazing Post",
    "description": "Nice post",
    "author": "FooBar"
}

此外,如果我删除 getter getAuthorAttribute()$appends 声明,我不会得到意外的 user 属性。

但我不想每次都使用这种方法,如果我想 return 我所有的 Post 使用:

return response()->json(Post::all(), 200);

有人知道为什么我使用 belongsTo 获得这个附加属性吗?

  • 此行为是性能问题。 当您第一次调用 $post->user 时,Laravel 从数据库中读取它并 将其保存在 $post->relation[] 中以供下次使用 。所以下次 Laravel 可以从数组中读取它并防止再次执行查询(如果你在多个地方使用它会很有用)。

  • 另外,用户也是一个属性和Laravel合并 当您调用 $model->toJson()$model->toArray()

  • 时,$attributes$relations 排列在一起

The Laravel's Model source code:

public function toArray()
{
    return array_merge($this->attributesToArray(), $this->relationsToArray());
}

public function jsonSerialize()
{
    return $this->toArray();
}

你的第一个方法很好,你只需要将 'user' 添加到 $hidden 数组

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  protected $table = 'posts';
  protected $appends = ['author'];

  protected $fillable = [
    'title',
    'description'
  ];

  protected $hidden = [
    'user_id',
    'created_at',
    'updated_at',
    'user', // <-- add 'user' here
  ];

  public function user()
  {
    return $this->belongsTo('App\User', 'user_id');
  }

  public function getAuthorAttribute()
  {
    return $this->user->username;
  }
}

您得到的模型将是:

{
  "id": 2,
  "title": "Amazing Post",
  "description": "Nice post",
  "author": "FooBar"
}