2015-05-29 6 views
5

sto usando eloqent per filtrare una serie di prodotti:multipla Dove In

Product::whereIn('color', $color)->whereIn('size', $size)->whereIn('price', $price)->get(); 

Ognuna delle variabili di cui sopra è una matrice di ID

$color = [1,2,4,5] 

la mia domanda è, è questo inefficiente quando l'utente non riesce a inviare attraverso un insieme di variabili, ad esempio non desidera alcun filtro colore in modo che la matrice sia:

$color = []; 

Ho provato -> toSql e produce l'istruzione SQL:

select * from `products` where `color` in (?, ?) and 0 = 1 and `price` in (?, ?, ?, ?, ?) 

In precedenza nessun filtro dimensioni è stato inviato attraverso.

Cosa significa 0 = 1? E questo è un modo inefficiente di gestire le cose?

risposta

4

Questa è una domanda molto interessante.

0 = 1 sarà sempre falso, quindi la query restituirà zero righe. Ma perché è questo?

Perché impostando

->whereIn('size', $size) 

laravel presuppone che si desidera sempre le righe restituite per stare con uno dei formati nella matrice passata. Se non si passa alcun valore nell'array, Laravel non può farlo where size IN() perché si tratta di un errore di sintassi (in pratica si dice di darmi tutte le righe che corrispondono a questa dimensione, ma non si superano le dimensioni). Quindi, nel caso in cui la matrice è vuota, mette semplicemente 0 = 1.

Al fine di dire a Laravel, se non viene passata alcuna dimensione, per non aggiungere la condizione per la dimensione basta mettere un semplice controllo prima di quello.

$product = new Product; 

if (!empty($sizes)) { 
    $product = $product->whereIn('size', $sizes); 
} 

$products = $product->get(); 

Btw questo comportamento è un hotfix. Nelle versioni precedenti di Laravel, se si passa un array vuoto si ha solo un'eccezione generata per un errore di sintassi. Ora è gestito semplicemente impostando 1 = 0

+1

Grazie. Quindi dovrei fare qualcosa come $ query = Product :: all(); poi fai un controllo dove per ogni filtro e se non vuoto fai $ query-> whereIn ('myfilter', $ requestedFilter); Non farebbe comunque più di una query e sarà inefficiente? – panthro

+1

@panthro no, 'Product :: all()' recupera tutti i prodotti contemporaneamente. Dovresti fare questo: '$ product = new Product ;, quindi controlla e aggiungi condizioni. – shaddy

+0

Quindi sarebbe qualcosa come $ product = new Product; // controlla i filtri; $ Prodotto-> get(); – panthro