2017-09-29 105 views
15

产品型号laravel whereHas结果怪异

public function country() { 
     return $this->hasMany('App\Models\ProductCountry', 'product_id', 'id'); 
    } 

控制器

$product = Product::where('mall_' . $this->mall_id, '=', 1) 
    ->whereHas('country', function ($i) use ($me) { 
     return $i->where('country_id', $me->country_id); 
    }) 
    ->find($key); 

原始SQL:

select * from `product` where `mall_3` = '1' and exists (select * from `product_country` where `product_country`.`product_id` = `product`.`id` and `country_id` = '109') and `product`.`id` = '3' and `product`.`deleted_at` is null limit 1 

上述SQL返回任何结果(当产品ID = 3

SQL以下返回正确的结果LT(当产品ID = 6)

select * from `product` where `mall_3` = '1' and exists (select * from `product_country` where `product_country`.`product_id` = `product`.`id` and `country_id` = '109') and `product`.`id` = '6' and `product`.`deleted_at` is null limit 1 

不知道,查询看起来好像没什么问题

以前的项目我得到这个问题也一样,在我使用查找和循环一次,而不是结束使用whereHas,但这个时候,我又遇到这个问题,并试图找出为什么,但浪费了几个小时,仍然没有头绪,下面是一种变通方法(忽略错误?)

$products = array(); 
foreach ($request->get('quantity') as $key => $var) { 
    if ($var > 0) { 
     $product = Product::with(['country'])->where('mall_' . $this->mall_id, '=', 1) 
        ->find($key); 

     foreach ($product->country as $c) { 
      if ($c->country_id == $me->country_id && !isset($products[$product->id])) { 
       //Do something here... 
      } 
     } 
    } 
} 

enter image description here

enter image description here

enter image description here

enter image description here

+0

你有没有尝试加入表而不是去存在检查? –

+0

尚未尝试加入,但想知道发生了什么与此存在检查查询,看起来不错,但不工作,真的很奇怪/错误 – user259752

+0

为什么在构建查询后使用'find()'? –

回答

0

首先第一件事情:

如果您使用eloquent(找方法),你可以这样做:

Product::find($id); 

和它会返回您提供的id的产品模型ed等于主键。说了这么多,没有必要使用whereHas(),因为它不起作用。取而代之的是find(),例如,您可以尝试get()first(),具体取决于您要查找的内容。

如果你想打印出你的查询,你可以用->toSql();来结束它,它会以字符串的形式打印查询(帮助很多!)。

我并不太重视的目标,但我敢肯定,如果你使用

dd(Product::where('mall_' . $this->mall_id, '=', 1) 
->whereHas('country', function ($i) use ($me) { 
    return $i->where('country_id', $me->country_id); 
}) 
->toSql()); 

你就可以比较你在做什么(因为你知道什么是正确的结果或查询应该是这样),并能够弄清楚。

毕竟,我们需要锻炼以探索我们的心灵!

+0

我认为这是mysql的错误,而不是laravel ,我使用whereHas,因为系统只向用户显示产品,如果用户在国内,认为where也会执行VALIDATION,所以不会有订单出国,你可以看到我写的2个查询,得到的结果和另一个没有结果,看着我上传的图像,已经证明,这两个查询应该有结果 – user259752

+0

我已经使用whereHas之前,没有任何麻烦,但我会尝试实施OP写的每当我回到家时,如果我有时间并希望,我可以就此事提供一些更新。 我对拉拉维尔(约4个月)有一点经验,但谈到雄辩时,我倾向于忘记他们给出的产品有时 – abr

3

我创建上面提到的表(给完全相同的关系,表名称,型号名称),并试图你的代码(通过给硬编码值)

public function try1(){ 
    $me = 109; 
    $key = 3; 
    $product = Product::where('mall_3' , '=', 1) 
     ->whereHas('country', function ($i) use ($me) { 
      return $i->where('country_id', $me); 
     }) 

     ->find($key); 

    return $product; 
} 

public function try2(){ 
    $me = 109; 
    $key = 6; 
    $product = Product::where('mall_3' , '=', 1) 
     ->whereHas('country', function ($i) use ($me) { 
      return $i->where('country_id', $me); 
     }) 

     ->find($key); 

    return $product; 
} 

,但得到了完美的结果

{"id":3,"mall_1":1,"mall_2":1,"mall_3":1} 

{"id":6,"mall_1":1,"mall_2":1,"mall_3":1} 

请检查,如果一切正常与数据库,检查如果E非常主键和外键被创建为“整数”。并检查db的“排序规则”以及表格。

+0

然后它的奇怪,我只是仔细检查,确认'product_country'.'product_id'是UNSIGNED INTEGER(10),我也检查了'product_country'和'产品'TABLE是相同的排序规则utf8_unicode_ci – user259752

3

这似乎没有与Laravel相关(因为使用MyAdmin直接运行查询时仍然没有结果)。

select * from `product` 
where true 
-- and `mall_3` = '1' 
and exists (
    select * from `product_country` 
    where true 
    and `product_country`.`product_id` = `product`.`id` 
    and `country_id` = '109' 
) 
and `product`.`id` = '3' 
and `product`.`deleted_at` is null 
limit 1 

再次运行查询,通过一个注释每个where条件一个(我加了一个true第一个条件很容易注释掉所有“and ...”行),看看你是否发现问题开始的地方。

(我曾尝试创建两个表,并且这两个查询返回正确的结果,顺便说一句。)

+1

检查后,我发现'deleted_at'对于'product'.'id' = 3不是NULL,是什么一个noob错误,谢谢 – user259752

+1

@ user259752但是这怎么可能?在你的屏幕截图中'deleted_at'是NULL。 –

+0

@PaulSpiegel你是对的,我没有检查我的截图上次,但现在我的数据库deleted_at真的为空 – user259752

0

试试这个,希望它会帮助你,

$products = array(); 
    foreach ($request->get('quantity') as $key => $var) { 
     if ($var > 0) { 
      $product = Product::where('mall_' . $this->mall_id, '=', 1) 
         ->leftjoin('product_country','product_country.product_id','=','product.id')->get(); 
      $products[$product->id] = ['product_id'=>$product->id,'country_id'=>$product->country_id];    
     } 
    } 
0

我想你应该改变你的关系从hasMany到belongsToMany的产品模型中的概念。
还通过将国家模型定义为第一个参数,将中间表名称作为第二个参数,然后将外键和主键定义为第三个和第四个参数来更新参数。 belongsToMany( '应用程序\型号\国家', 'product_country', 'PRODUCT_ID', 'COUNTRY_ID')

产品型号

public function country() { 
    return $this->belongsToMany('App\Models\Country', 'product_country','product_id', 'country_id'); 
} 

由于各个国家可能属于很多产品和每个产品可能属于许多国家。

0

我知道这个线程有点陈旧,但是我的团队实际上和Laravel以及MySQL 5.7.18上的whereHas(MySQL EXISTS)有类似的问题。

只要我们升级MySQL,相同的查询开始完全按照预期返回。我还没有弄清楚这是否是5.7.18的错误,但我怀疑它可能是。