laravel - 模型追加,包括查询中的整个关系
问题描述
编辑:我能够看到我的回复中包含的关系,但我仍然不知道为什么。
在我的Customer
模型上,我有:
protected $appends = [
'nps',
'left_feedback',
'full_name',
'url'
];
访问器如下:
/**
* Accessor
*/
public function getNpsAttribute() {
if ($this->reviews->count() > 0) {
return $this->reviews->first()->nps;
} else {
return "n/a";
}
}
/**
* Accessor
*/
public function getLeftFeedbackAttribute() {
if ($this->reviews && $this->reviews->count() > 0 && $this->reviews->first()->feedback != null) {
return "Yes";
} else {
return "No";
}
}
/**
* Accessor
*/
public function getFullNameAttribute() {
return ucwords($this->first_name . ' ' . $this->last_name);
}
/**
* Accessor
*/
public function getUrlAttribute() {
$location = $this->location;
$company = $location->company;
$account_id = $company->account->id;
return route('customers.show', ['account_id' => $account_id, 'company' => $company, 'location' => $location, 'customer' => $this]);
}
因此,如果我注释掉该$appends
属性,我会得到我最初想要的响应,而客户不会在我的响应中返回所有关系。
但我确实想要我的客户对象上的那些附加字段。我不明白为什么它会包括它在响应中使用的所有关系。我正在返回特定的字符串。
那么有没有办法让我的$appends
而不是它在访问器中使用的所有关系都被包含在内?
原始问题:
我正在查询属于客户的评论。我想将客户关系作为评论的一部分,但我不想包括客户关系。
$reviews = $reviews->with(['customer' => function($query) {
$query->setEagerLoads([]);
$query->select('id', 'location_id', 'first_name', 'last_name');
}]);
$query->setEagerLoads([]);
在这种情况下不起作用。
我也试过$query->without('location');
了,但它仍然包含在内
我应该注意我没有$with
在模型上填充任何属性。
这是Review
模型关系:
public function customer() {
return $this->belongsTo('App\Customer');
}
这是Customer
模型关系:
public function reviews() {
return $this->hasMany('App\Review');
}
// I dont want these to be included
public function location() {
return $this->belongsTo('App\Location');
}
public function reviewRequests() {
return $this->hasMany('App\ReviewRequest');
}
在响应中,它看起来像:
'review' => [
'id'=> '1'
'customer => [
'somecol' => 'test',
'somecolagain' => 'test',
'relation' => [
'relation' => [
]
],
'relation' => [
'somecol' => 'sdffdssdf'
]
]
]
因此,一系列关系最终被加载,我不想要它们。
解决方案
正如您在对主要问题的一条评论中所说,由于附加的访问器,您得到了关系。
让我向您展示应该如何完成(我将复制粘贴您的代码并简单地编辑一些部分,但您仍然可以复制粘贴我的代码并将其放入您的代码中,并且将以相同的方式工作,但会阻止添加关系)和然后让我解释一下为什么会这样:
/**
* Accessor
*/
public function getNpsAttribute() {
if ($this->reviews()->count() > 0) {
return $this->reviews()->first()->nps;
} else {
return "n/a";
}
}
/**
* Accessor
*/
public function getLeftFeedbackAttribute() {
return $this->reviews()->count() > 0 &&
$this->reviews()->first()->feedback != null
? "Yes"
: "No";
}
/**
* Accessor
*/
public function getFullNameAttribute() {
return ucwords($this->first_name . ' ' . $this->last_name);
}
/**
* Accessor
*/
public function getUrlAttribute() {
$location = $this->location()->first();
$company = $location->company;
$account_id = $company->account->id;
return route('customers.show', ['account_id' => $account_id, 'company' => $company, 'location' => $location, 'customer' => $this]);
}
如您所见,我已将 any 更改$this->relation
为$this->relation()->first()
or $this->relation->get()
。
如果您访问任何模型的关系,因为$this->relation
它会将其添加到预先加载(已加载)中,因此它会真正获取关系数据并将其存储在模型的数据中,因此下次您$this->relation
再次访问时,它不必去数据库和查询再次。
因此,为防止这种情况,您必须访问关系 as $this->relation()
,这将返回一个查询构建器,然后您可以执行->count()
or->exists()
或->get()
or->first()
或任何其他有效的查询构建器方法,但是作为查询构建器访问关系将阻止获取数据和将它存储在模型中(我知道正在做->get()
或->first()
将要获取数据,但您不是直接通过模型获取它,而是通过查询构建器关系获取它,这是不同的)。
这样,您将防止将数据存储在模型上,从而给您带来问题。
您也可以使用API Resources
,它用于将模型或集合映射到所需的输出。
最后一件事,如果你可以使用它$this->relation()->exists()
来代替它,这$this->relation()->count() > 0
将有助于更快地完成它,大多数情况下,任何数据库在查看数据是否存在(count >= 1
exists
推荐阅读
- html - 使用 Komodo IDE 12:不知道如何将 index.html 链接到 style.css
- python - 如何在 Python 中检查登录用户是否具有系统管理员权限
- python - Errno 13 打开时,即使启用了权限
- r - 如何通过 fitdistrplus 包选择分布参数?
- ios - 基于模板创建自定义视图
- django - 从 int:pk 更改为 Slug
- python-3.x - 如何在python中删除重复项?
- backbase - 错误没有导出成员“HTTP_PARAMS_FACTORY”
- javascript - 有没有办法修改 R 传单中现有标记/形状的不透明度(有光泽)
- java - 使用 application.yml 将 Spring Boot 记录到 Windows PC 中的文件