Laravel 5的问题在哪里 [英] Laravel 5 issue with wherePivot
问题描述
- > wherePivot()
在多对多关系中工作的问题。当我 dd()
时,SQL看起来像Eloquent正在透视表中的一个`pose_state````````````为空。 我希望这是一个简单的错误,而不是一个错误。任何想法都不胜感激。
数据库结构
姿势
id
名称
类型
状态
id
name
machine_name
pose_state
pose_id
state_id
status
模型
姿势
<?php命名空间应用程序;
使用DB;
使用App \State;
使用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命名空间应用程序;
使用Illuminate\Database\Eloquent\Model;
class State扩展模型{
public function poses()
{
return $ this-> belongsToMany('Pose')
- > withPivot('status_id')
- > withTimestamps();
}
}
PosesController function
public function listPosesForReview(){
$ poses = Pose :: withPendingReviews() - > get );
dd($ poses-> toArray());
}
SQL
select
`states`。*,`pose_state`.`pose_id`为`pivot_pose_id`,
`pose_state`.`state_id`作为`pivot_state_id`,
`pose_state`.`status_id`为`pivot_status_id`,
`pose_state`.`created_at`为`pivot_created_at`,
`pose_state`.`updated_at`为` pivot_updated_at`
从
`states`内部连接`pose_state`在`states`.`id` =`pose_state`.`state_id`
其中
`pose_state`.`pose_id `是null和`pose_state`.`status_id` =?
编辑
当我更新我的代码去除它的作用范围。感谢@Deefour把我放在正确的道路上!也许范围有其他的东西,我失踪了。
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);
});
}
code> scopeWithPendingReviews()是滥用范围的预期用途。
除此之外,我相信你没有使用 wherePivot()
正确。根据 来源
public function wherePivot($ column,$ operator = null,$ value = null,$ boolean ='and')
但您将其视为
public function wherePivot($ column,$ value = null,$ boolean ='and')
这意味着
- > wherePivot 'status_id',10)
应该是
- > wherePivot('status_id','=',10)
回应评论
范围应该被认为是可重用的一组条件,以附加到现有查询,即使该查询只是简单的
SomeMode l :: newQuery()
这个想法是,一个预先存在的查询将进一步改进:'scoped')根据scope方法中的条件,不生成新查询,绝对不会根据关联的模型生成新的查询。
由默认情况下,传递给scope方法的第一个也是唯一的参数是查询构建器实例本身。
您的姿势
model真的是一个状态
表的查询,一旦你这样做
code> $ this-> states()
这就是为什么你的SQL显示为确实。这也是您滥用范围的明确指标。范围可能会像这样
public function scopeWithPendingReviews($ query){
$ query-> join 'pose_state','poses.id','=','pose_state.pose.id')
- > where('status_id',10);
}
与新的 pendingReviews()$ c不同$ c>方法,它返回基于
状态
模型的查询,该范围将在 Pose
现在可以按照您原来的目的使用您的范围。
$ poses = Pose :: withPendingReviews();
可以翻译成更详细的
$ poses = Pose :: newQuery() - > withPendingReviews();
注意上面的范围不会返回值。它接受现有的查询构建器对象并添加到其中。
此问题的另一个答案填满了错误信息。
- 您不能在声明中使用
wherePivot()
。 - 您的使用
withTimestamps()
与您的问题无关 - 您不必做任何定制工作来获取时间戳。添加
withTimestamps()
调用,就像所需要的一样。只需确保您的连接表中有created_at
和updated_at
列。
I am working with Laravel 5 and I am having issue getting ->wherePivot()
to work on a Many-to-Many relationship. When I dd()
the SQL it looks like Eloquent is looking for records in the pivot table with a `pose_state`.`pose_id` is null`.
I am hoping it is a simple error and not a bug. Any ideas are appreciated.
Database Structure
pose
id
name
type
state
id
name
machine_name
pose_state
pose_id
state_id
status
Models
Pose
<?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);
}
}
State
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class State extends Model {
public function poses()
{
return $this->belongsToMany('Pose')
->withPivot('status_id')
->withTimestamps();
}
}
PosesController function
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` = ?
EDIT
When I updated my code to removing the scope it worked. Thanks @Deefour for putting me on the right path! Maybe scope has something else to that I am missing.
public function pendingReviews()
{
return $this->states()
->wherePivot('status_id','=', 10);
}
YET ANOTHER EDIT
I finally got this to work. The solution above was giving me duplicate entries. No idea why this works, but it does, so I will stick with it.
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);
});
}
I think your implementation of scopeWithPendingReviews()
is an abuse of the intended use of scopes.
That aside, I believe you're not using wherePivot()
properly. According to the source, the method signature is
public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
but you're treating it as
public function wherePivot($column, $value = null, $boolean = 'and')
This means
->wherePivot('status_id',10)
should be
->wherePivot('status_id', '=', 10)
Responding to Comments
A scope should be thought of as a reusable set of conditions to append to an existing query, even if that query is simply
SomeModel::newQuery()
The idea is that a pre-existing query would be further refined (read: 'scoped') by the conditions within the scope method, not to generate a new query, and definitely not to generate a new query based on an associated model.
By default, the first and only argument passed to a scope method is the query builder instance itself.
Your scope implementation on your Pose
model was really a query against the states
table as soon as you did this
$this->states()
This is why your SQL appears as it does. It's also a clear indicator you're misusing scopes. A scope might instead look like this
public function scopeWithPendingReviews($query) {
$query->join('pose_state', 'poses.id', '=', 'pose_state.pose.id')
->where('status_id', 10);
}
Unlike your new pendingReviews()
method which is returning a query based on the State
model, this scope will refine a query on the Pose
model.
Now you can use your scope as you originally intended.
$poses = Pose::withPendingReviews();
which could be translated into the more verbose
$poses = Pose::newQuery()->withPendingReviews();
Notice also the scope above doesn't return a value. It's accepting the existing query builder object and adding onto it.
The other answer to this question is filled with misinformation.
- You cannot use
wherePivot()
as is claims. - Your use of
withTimestamps()
is not at all related to your problem - You don't have to do any "custom work" to get timestamps working. Adding the
withTimestamps()
call as you did is all that is needed. Just make sure you have acreated_at
andupdated_at
column in your join table.
这篇关于Laravel 5的问题在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!