Laravel 5 wherePivot 问题
Laravel 5 issue with wherePivot
我正在与 Laravel 5 合作,但在让 ->wherePivot()
处理多对多关系时遇到问题。当我 dd()
SQL 时,它看起来像 Eloquent 正在寻找枢轴 table 中带有 `pose_state` 的记录。`pose_id`为空`。
我希望这是一个简单的错误,而不是错误。任何想法表示赞赏。
数据库结构
姿势
id
name
type
状态
id
name
machine_name
pose_state
pose_id
state_id
status
型号
姿势
<?php namespace App;
use DB;
use App\State;
use Illuminate\Database\Eloquent\Model;
class Pose extends Model {
public function states()
{
return $this->belongsToMany('App\State')
->withPivot('status_id')
->withTimestamps();
}
public function scopeWithPendingReviews()
{
return $this->states()
->wherePivot('status_id',10);
}
}
州
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class State extends Model {
public function poses()
{
return $this->belongsToMany('Pose')
->withPivot('status_id')
->withTimestamps();
}
}
姿势控制器函数
public function listPosesForReview(){
$poses = Pose::withPendingReviews()->get();
dd($poses->toArray() );
}
SQL
select
`states`.*, `pose_state`.`pose_id` as `pivot_pose_id`,
`pose_state`.`state_id` as `pivot_state_id`,
`pose_state`.`status_id` as `pivot_status_id`,
`pose_state`.`created_at` as `pivot_created_at`,
`pose_state`.`updated_at` as `pivot_updated_at`
from
`states` inner join `pose_state` on `states`.`id` = `pose_state`.`state_id`
where
`pose_state`.`pose_id` is null and `pose_state`.`status_id` = ?
编辑
当我更新我的代码以删除它工作的范围时。感谢@Deefour 让我走上了正确的道路!也许 scope 还有其他我所缺少的东西。
public function pendingReviews()
{
return $this->states()
->wherePivot('status_id','=', 10);
}
又一次编辑
我终于让它工作了。上面的解决方案给了我重复的条目。不知道为什么会这样,但确实如此,所以我会坚持下去。
public function scopeWithStatusCode($query, $tag)
{
$query->with(['states' => function($q) use ($tag)
{
$q->wherePivot('status_id','=', $tag);
}])
->whereHas('states',function($q) use ($tag)
{
$q->where('status_id', $tag);
});
}
我认为您对 scopeWithPendingReviews()
的实施滥用了作用域的预期用途。
范围应该被认为是附加到现有查询的一组可重复使用的条件,即使该查询只是
SomeModel::newQuery()
想法是通过范围方法内的条件进一步细化(阅读:'scoped')预先存在的查询,而不是生成新查询,绝对不会生成新查询基于关联模型。
默认情况下,传递给范围方法的第一个也是唯一一个参数是查询生成器实例本身。
您在 Pose
模型上的作用域实现实际上是对 states
table 的查询,一旦您这样做
$this->states()
这就是您的 SQL 出现的原因。这也是您滥用范围的明确指示。范围可能看起来像这样
public function scopeWithPendingReviews($query) {
$query->join('pose_state', 'poses.id', '=', 'pose_state.pose.id')
->where('status_id', 10);
}
与 return 基于 State
模型查询的新 pendingReviews()
方法不同,此范围将优化 Pose
模型上的查询。
现在您可以按原计划使用范围。
$poses = Pose::withPendingReviews();
这可以翻译成更冗长的
$poses = Pose::newQuery()->withPendingReviews();
另请注意,上面的范围没有 return 值。它正在接受现有的查询构建器对象并添加到它上面。
这个问题的另一个答案充满了错误信息。
- 您不能按声明使用
wherePivot()
。
- 您对
withTimestamps()
的使用与您的问题完全无关
- 您无需执行任何“自定义工作”即可使时间戳正常工作。只需像您所做的那样添加
withTimestamps()
调用即可。只需确保您的连接 table. 中有 created_at
和 updated_at
列
我认为你的作用域实现没问题,我看到的问题只是一个错字。您的架构显示该字段称为 status
但您的 where 条件指的是 status_id
尝试:
->wherePivot('status', 10);
此外,withTimestamps()
方法会导致问题。您的数据透视表架构中没有时间戳(如我所见),因此您不应该将它们放在您的关系定义中,因为它试图获取与关系 created/updated 时相关的时间戳。如果您将数据透视 table 架构设置为具有时间戳字段,则可以执行此操作,但我认为您必须执行一些自定义工作才能正确保存时间戳。
这对我有用 (Laravel 5.3):
$task = App\Models\PricingTask::find(1);
$task->products()->wherePivot('taggable_type', 'product')->get();
如果您在 wherePivot
中使用的列尚未添加到 withPivot
。
,您也可能遇到此问题(return 无结果)
我正在与 Laravel 5 合作,但在让 ->wherePivot()
处理多对多关系时遇到问题。当我 dd()
SQL 时,它看起来像 Eloquent 正在寻找枢轴 table 中带有 `pose_state` 的记录。`pose_id`为空`。
我希望这是一个简单的错误,而不是错误。任何想法表示赞赏。
数据库结构
姿势
id
name
type
状态
id
name
machine_name
pose_state
pose_id
state_id
status
型号
姿势
<?php namespace App;
use DB;
use App\State;
use Illuminate\Database\Eloquent\Model;
class Pose extends Model {
public function states()
{
return $this->belongsToMany('App\State')
->withPivot('status_id')
->withTimestamps();
}
public function scopeWithPendingReviews()
{
return $this->states()
->wherePivot('status_id',10);
}
}
州
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class State extends Model {
public function poses()
{
return $this->belongsToMany('Pose')
->withPivot('status_id')
->withTimestamps();
}
}
姿势控制器函数
public function listPosesForReview(){
$poses = Pose::withPendingReviews()->get();
dd($poses->toArray() );
}
SQL
select
`states`.*, `pose_state`.`pose_id` as `pivot_pose_id`,
`pose_state`.`state_id` as `pivot_state_id`,
`pose_state`.`status_id` as `pivot_status_id`,
`pose_state`.`created_at` as `pivot_created_at`,
`pose_state`.`updated_at` as `pivot_updated_at`
from
`states` inner join `pose_state` on `states`.`id` = `pose_state`.`state_id`
where
`pose_state`.`pose_id` is null and `pose_state`.`status_id` = ?
编辑
当我更新我的代码以删除它工作的范围时。感谢@Deefour 让我走上了正确的道路!也许 scope 还有其他我所缺少的东西。
public function pendingReviews()
{
return $this->states()
->wherePivot('status_id','=', 10);
}
又一次编辑
我终于让它工作了。上面的解决方案给了我重复的条目。不知道为什么会这样,但确实如此,所以我会坚持下去。
public function scopeWithStatusCode($query, $tag)
{
$query->with(['states' => function($q) use ($tag)
{
$q->wherePivot('status_id','=', $tag);
}])
->whereHas('states',function($q) use ($tag)
{
$q->where('status_id', $tag);
});
}
我认为您对 scopeWithPendingReviews()
的实施滥用了作用域的预期用途。
范围应该被认为是附加到现有查询的一组可重复使用的条件,即使该查询只是
SomeModel::newQuery()
想法是通过范围方法内的条件进一步细化(阅读:'scoped')预先存在的查询,而不是生成新查询,绝对不会生成新查询基于关联模型。
默认情况下,传递给范围方法的第一个也是唯一一个参数是查询生成器实例本身。
您在 Pose
模型上的作用域实现实际上是对 states
table 的查询,一旦您这样做
$this->states()
这就是您的 SQL 出现的原因。这也是您滥用范围的明确指示。范围可能看起来像这样
public function scopeWithPendingReviews($query) {
$query->join('pose_state', 'poses.id', '=', 'pose_state.pose.id')
->where('status_id', 10);
}
与 return 基于 State
模型查询的新 pendingReviews()
方法不同,此范围将优化 Pose
模型上的查询。
现在您可以按原计划使用范围。
$poses = Pose::withPendingReviews();
这可以翻译成更冗长的
$poses = Pose::newQuery()->withPendingReviews();
另请注意,上面的范围没有 return 值。它正在接受现有的查询构建器对象并添加到它上面。
这个问题的另一个答案充满了错误信息。
- 您不能按声明使用
wherePivot()
。 - 您对
withTimestamps()
的使用与您的问题完全无关 - 您无需执行任何“自定义工作”即可使时间戳正常工作。只需像您所做的那样添加
withTimestamps()
调用即可。只需确保您的连接 table. 中有
created_at
和 updated_at
列
我认为你的作用域实现没问题,我看到的问题只是一个错字。您的架构显示该字段称为 status
但您的 where 条件指的是 status_id
尝试:
->wherePivot('status', 10);
此外,withTimestamps()
方法会导致问题。您的数据透视表架构中没有时间戳(如我所见),因此您不应该将它们放在您的关系定义中,因为它试图获取与关系 created/updated 时相关的时间戳。如果您将数据透视 table 架构设置为具有时间戳字段,则可以执行此操作,但我认为您必须执行一些自定义工作才能正确保存时间戳。
这对我有用 (Laravel 5.3):
$task = App\Models\PricingTask::find(1);
$task->products()->wherePivot('taggable_type', 'product')->get();
如果您在 wherePivot
中使用的列尚未添加到 withPivot
。