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...
}
}
}
}
首先第一件事情:
如果您使用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());
你就可以比较你在做什么(因为你知道什么是正确的结果或查询应该是这样),并能够弄清楚。
毕竟,我们需要锻炼以探索我们的心灵!
我认为这是mysql的错误,而不是laravel ,我使用whereHas,因为系统只向用户显示产品,如果用户在国内,认为where也会执行VALIDATION,所以不会有订单出国,你可以看到我写的2个查询,得到的结果和另一个没有结果,看着我上传的图像,已经证明,这两个查询应该有结果 – user259752
我已经使用whereHas之前,没有任何麻烦,但我会尝试实施OP写的每当我回到家时,如果我有时间并希望,我可以就此事提供一些更新。 我对拉拉维尔(约4个月)有一点经验,但谈到雄辩时,我倾向于忘记他们给出的产品有时 – abr
我创建上面提到的表(给完全相同的关系,表名称,型号名称),并试图你的代码(通过给硬编码值)
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的“排序规则”以及表格。
然后它的奇怪,我只是仔细检查,确认'product_country'.'product_id'是UNSIGNED INTEGER(10),我也检查了'product_country'和'产品'TABLE是相同的排序规则utf8_unicode_ci – user259752
这似乎没有与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 ...
”行),看看你是否发现问题开始的地方。
(我曾尝试创建两个表,并且这两个查询返回正确的结果,顺便说一句。)
检查后,我发现'deleted_at'对于'product'.'id' = 3不是NULL,是什么一个noob错误,谢谢 – user259752
@ user259752但是这怎么可能?在你的屏幕截图中'deleted_at'是NULL。 –
@PaulSpiegel你是对的,我没有检查我的截图上次,但现在我的数据库deleted_at真的为空 – user259752
试试这个,希望它会帮助你,
$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];
}
}
我想你应该改变你的关系从hasMany到belongsToMany的产品模型中的概念。
还通过将国家模型定义为第一个参数,将中间表名称作为第二个参数,然后将外键和主键定义为第三个和第四个参数来更新参数。 belongsToMany( '应用程序\型号\国家', 'product_country', 'PRODUCT_ID', 'COUNTRY_ID')
产品型号
public function country() {
return $this->belongsToMany('App\Models\Country', 'product_country','product_id', 'country_id');
}
由于各个国家可能属于很多产品和每个产品可能属于许多国家。
我知道这个线程有点陈旧,但是我的团队实际上和Laravel以及MySQL 5.7.18上的whereHas(MySQL EXISTS)有类似的问题。
只要我们升级MySQL,相同的查询开始完全按照预期返回。我还没有弄清楚这是否是5.7.18的错误,但我怀疑它可能是。
你有没有尝试加入表而不是去存在检查? –
尚未尝试加入,但想知道发生了什么与此存在检查查询,看起来不错,但不工作,真的很奇怪/错误 – user259752
为什么在构建查询后使用'find()'? –