2017-09-29 93 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的錯誤,但我懷疑它可能是。