Laravel 5的问题在哪里 [英] Laravel 5 issue with wherePivot

查看:110
本文介绍了Laravel 5的问题在哪里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在和Laravel 5一起工作,而我正在获得 - > 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()方法,它返回基于状态模型的查询,该范围将在 Pose



现在可以按照您原来的目的使用您的范围。

  $ poses = Pose :: withPendingReviews(); 

可以翻译成更详细的

  $ poses = Pose :: newQuery() - > withPendingReviews(); 

注意上面的范围不会返回值。它接受现有的查询构建器对象并添加到其中。



此问题的另一个答案填满了错误信息。


  1. 您不能在声明中使用 wherePivot()

  2. 您的使用 withTimestamps()与您的问题无关

  3. 您不必做任何定制工作来获取时间戳。添加 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.

  1. You cannot use wherePivot() as is claims.
  2. Your use of withTimestamps() is not at all related to your problem
  3. 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 a created_at and updated_at column in your join table.

这篇关于Laravel 5的问题在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆