Laravel 5 Eloquent 在多个级别上将关系附加到 JSON
Laravel 5 Eloquent appending relationships to JSON on multiple levels
因此很容易在模型中包含关系,例如:
class User extends Model {
protected $with=['roles']
}
class Role extends Model {
protected $with=['permissions']
}
当有对用户资源的获取请求时,它将自动包含关联的角色。
但在此设置中,与用户资源一起返回的角色资源还包括它自己的包含关系,例如:
{user:{id:1, roles:[{id:1, permissions:[{id:1..
这会生成巨大的对象,其中大部分包含不必要的相关子模型。
我可以通过设置属性来替换默认关系来解决这个问题,但我正在处理的 API 有 30 多个资源,而且这条路径不是理想的,因为它需要我写很多模型上的重复代码。
有没有办法轻松管理附加关系的深度?
我想是这样的:
class Role extends Model {
protected $with=['permissions'];
protected $includeWith=[]; // role wont have the permissions appended when included
}
如果对象大小和内存使用成为问题,那么在某些情况下您只需要关闭 with。
其他代码本身不用改,但总的来说查询会多一些。在需要的地方,您可以进行显式预加载或惰性预加载。
您可以使用 $appends:
滚动您自己的属性,而不是 built-in '$with' 数组
class User extends Model
{
protected $appends = ['roles_list'];
// ...
// other stuff here, like relationship definitions
// ...
public function getRolesListAttribute()
{
return $this->roles;
//OR build 'roles_list' manually, returning whatever you like.
}
}
唯一的缺点是您必须在接收端注意 'roles_list' 而不是 'roles'。
如果有人对此问题的解决方案仍然感兴趣:Laravel 5.5 引入了 Api Resources,这是组织 api 回复的好方法。只是不要在您的模型中包含任何关系并将它们附加到资源上。
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class UserResource extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'roles'=> $this->roles
];
}
}
如果您已经声明了关系并且想要附加该关系数据,那么您可以像下面的示例那样做
class User extends Model
{
/* your other code */
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'company_list',
];
// ...
// other stuff here, like relationship definitions
// ...
/**
* Get the Companies List with User Id.
*
* @return array
*/
public function getCompanyListAttribute()
{
return $this->company()->get();
}
/**
* Get the company for the user.
*
* one-to-many relationship
*/
public function Company()
{
return $this->hasMany(CompanyList::class, 'company_owner_id');
}
}
现在,它将在用户详细信息数组中附加公司详细信息
例如,我使用这样的用户 ID 获取用户详细信息
echo User::find(2);
然后它将 returns 数组如下
Array ( [id] => 2 [name] => Merritt Roob [email] => kerluke.mariano@example.net [email_verified_at] => 2021-12-07T08:34:43.000000Z [contact] => [profile_photo_path] => [created_at] => 2021-12-07T08:34:43.000000Z [updated_at] => 2021-12-07T08:34:43.000000Z [company_list] => Array ( [0] => Array ( [id] => 1 [company_name] => Prof. Dorcas Strosin II [company_email] => paxton91@example.com [company_contact] => 1-986-702-4140 [company_owner_id] => 2 [created_at] => 2021-12-07T08:34:43.000000Z [updated_at] => 2021-12-07T08:34:43.000000Z ) ) )
我希望上面的例子对其他人有帮助谢谢
因此很容易在模型中包含关系,例如:
class User extends Model {
protected $with=['roles']
}
class Role extends Model {
protected $with=['permissions']
}
当有对用户资源的获取请求时,它将自动包含关联的角色。
但在此设置中,与用户资源一起返回的角色资源还包括它自己的包含关系,例如:
{user:{id:1, roles:[{id:1, permissions:[{id:1..
这会生成巨大的对象,其中大部分包含不必要的相关子模型。
我可以通过设置属性来替换默认关系来解决这个问题,但我正在处理的 API 有 30 多个资源,而且这条路径不是理想的,因为它需要我写很多模型上的重复代码。
有没有办法轻松管理附加关系的深度?
我想是这样的:
class Role extends Model {
protected $with=['permissions'];
protected $includeWith=[]; // role wont have the permissions appended when included
}
如果对象大小和内存使用成为问题,那么在某些情况下您只需要关闭 with。
其他代码本身不用改,但总的来说查询会多一些。在需要的地方,您可以进行显式预加载或惰性预加载。
您可以使用 $appends:
滚动您自己的属性,而不是 built-in '$with' 数组class User extends Model
{
protected $appends = ['roles_list'];
// ...
// other stuff here, like relationship definitions
// ...
public function getRolesListAttribute()
{
return $this->roles;
//OR build 'roles_list' manually, returning whatever you like.
}
}
唯一的缺点是您必须在接收端注意 'roles_list' 而不是 'roles'。
如果有人对此问题的解决方案仍然感兴趣:Laravel 5.5 引入了 Api Resources,这是组织 api 回复的好方法。只是不要在您的模型中包含任何关系并将它们附加到资源上。
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class UserResource extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'roles'=> $this->roles
];
}
}
如果您已经声明了关系并且想要附加该关系数据,那么您可以像下面的示例那样做
class User extends Model
{
/* your other code */
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'company_list',
];
// ...
// other stuff here, like relationship definitions
// ...
/**
* Get the Companies List with User Id.
*
* @return array
*/
public function getCompanyListAttribute()
{
return $this->company()->get();
}
/**
* Get the company for the user.
*
* one-to-many relationship
*/
public function Company()
{
return $this->hasMany(CompanyList::class, 'company_owner_id');
}
}
现在,它将在用户详细信息数组中附加公司详细信息
例如,我使用这样的用户 ID 获取用户详细信息
echo User::find(2);
然后它将 returns 数组如下
Array ( [id] => 2 [name] => Merritt Roob [email] => kerluke.mariano@example.net [email_verified_at] => 2021-12-07T08:34:43.000000Z [contact] => [profile_photo_path] => [created_at] => 2021-12-07T08:34:43.000000Z [updated_at] => 2021-12-07T08:34:43.000000Z [company_list] => Array ( [0] => Array ( [id] => 1 [company_name] => Prof. Dorcas Strosin II [company_email] => paxton91@example.com [company_contact] => 1-986-702-4140 [company_owner_id] => 2 [created_at] => 2021-12-07T08:34:43.000000Z [updated_at] => 2021-12-07T08:34:43.000000Z ) ) )
我希望上面的例子对其他人有帮助谢谢