Filtraggio dei risultati usando LIKE


16

Considera queste tre stringhe "pagliaio":

un) foo bar

b) welcome to foo bar industries

c) foo barer

E ora il mio "ago":

foo bar

(Heh)

Vorrei che il mio filtro corrispondesse al mio ago con le corde del pagliaio a & b ma non c. Ho provato:

$collection->addAttributeToFilter('name', array('like' => '%'.$needle.'%'));

Ma quanto sopra corrisponde a c.

Ho anche provato:

$collection->addAttributeToFilter('name', array('like' => '% '.$needle.' %')); // Note the spaces

Quanto sopra corrisponde solo a b.

Ogni aiuto è molto apprezzato.

Risposte:


37

Fai una prova e vedi se si adatta:

$collection->addAttributeToFilter('name', array(
    array('like' => '% '.$needle.' %'), //spaces on each side
    array('like' => '% '.$needle), //space before and ends with $needle
    array('like' => $needle.' %') // starts with needle and space after
));

Passare il secondo parametro come una matrice di array concatenerà le condizioni usando OR


Funziona :) Non sapevo del trucco dell'array, grazie.
beingalex,

Con i modelli personalizzati / non-eav addAttributeToFilterdevono essere sostituiti con addFieldToFilter.
jvalanen,

C'è un modo per determinare quale array ha restituito un risultato? Sto usando questo metodo per cercare una collezione di modelli personalizzati (nome, descrizione, campi nome_alternativo) e mi piacerebbe sapere se il risultato è stato colpito a causa della descrizione (per includere un elemento dell'interfaccia utente aggiuntivo nei risultati di ricerca).
pspahn

3
@pspahn Non è semplice. È possibile scorrere i risultati dopo aver eseguito la selezione e verificare se l'ago viene trovato in uno dei campi desiderati.
Marius

9

Una possibile soluzione è utilizzare REGEXPinvece di LIKE:

$collection->addAttributeToFilter('name', array('regexp' => '[[:<:]]'.$needle.'[[:>:]]'));

Dalla documentazione di MySQL :

[[: <:]], [[:>:]]

Questi marcatori indicano i confini delle parole. Corrispondono all'inizio e alla fine delle parole, rispettivamente. Una parola è una sequenza di caratteri parola che non è preceduta o seguita da caratteri parola. Un carattere parola è un carattere alfanumerico nella classe alnum o un trattino basso (_).

Nota che se $needlepuò contenere caratteri che hanno significati speciali nelle espressioni regolari POSIX, devi evitarli. Vedi anche: /programming/4024188/php-function-to-escape-mysql-regexp-syntax


3

La risposta accettata non funziona correttamente. Controlla solo lo spazio prima e dopo il testo.

Supponiamo che tu abbia il seguente elenco

  • Giacca
  • Giacca estiva
  • Giacca invernale

Ora se provi a cercare con la giacca utilizzando la risposta accettata, verranno restituiti solo Summer Jacket e Winter Jacket

Penso che seguire la soluzione sia migliore

$collection->addAttributeToFilter('name', array('like' => '%' . $needle. '%'));

Non coprirebbe il caso (c) della domanda (cioè corrisponderebbe anche al "rivestimento"). Invece, una quarta condizione ['eq' => $needle]potrebbe essere aggiunta per trovare corrispondenze esatte (o meglio, usare la soluzione regex che trova tutti i confini, non solo gli spazi)
Fabian Schmengler

sopra il codice è in grado di trovare le corrispondenze esatte. L'ho controllato
Dinesh Yadav il

Non ne dubitavo. Ma trova di più, cosa che non dovrebbe. Almeno se hai gli stessi requisiti della domanda originale: non trovare "foo barer" quando cerchi "foo bar"
Fabian Schmengler

Si hai ragione. La risposta accettata non funzionava correttamente per me, quindi ho suggerito il semplice filtro a una riga per ottenere gli oggetti allo stesso modo.
Dinesh Yadav,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.