Filtrowanie wyników za pomocą LIKE


16

Rozważ te trzy ciągi „stogu siana”:

za) foo bar

b) welcome to foo bar industries

do) foo barer

A teraz moja „igła”:

foo bar

(Heh)

Chciałbym, aby mój filtr pasował do mojej igły z ciągami stogu siana a & b, ale nie c. Próbowałem:

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

Ale powyższe pasuje do c.

Próbowałem także:

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

Powyższe pasuje tylko do b.

Każda pomoc jest mile widziana.

Odpowiedzi:


37

Spróbuj i sprawdź, czy pasuje:

$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
));

Przekazanie drugiego parametru jako tablicy tablic połączy warunki przy użyciu OR


To działa :) Nie wiedziałem o sztuczce tablicowej, dzięki.
beingalex

Modele niestandardowe / inne niż eav addAttributeToFilterpowinny zostać zastąpione przez addFieldToFilter.
jvalanen

Czy istnieje sposób ustalenia, która tablica zwróciła wynik? Używam tej metody do wyszukiwania kolekcji modelu niestandardowego (nazwa, opis, nazwa alternatywna) i chciałbym wiedzieć, czy wynik został trafiony z powodu opisu (aby uwzględnić dodatkowy element interfejsu użytkownika w wynikach wyszukiwania).
pspahn

3
@pspahn Nie jest to proste. Możesz wykonać pętlę wyników po wykonaniu zaznaczenia i sprawdzić, czy igła znajduje się w dowolnym polu, które chcesz.
Marius

9

Możliwym rozwiązaniem jest użycie REGEXPzamiast LIKE:

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

Z dokumentacji MySQL :

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

Te znaczniki oznaczają granice słów. Dopasowują odpowiednio początek i koniec słów. Słowo jest ciągiem znaków słownych, które nie są poprzedzane znakami słownymi ani po nich nie występują. Znak słowny to znak alfanumeryczny w klasie alnum lub znak podkreślenia (_).

Zauważ, że jeśli $needlemogą zawierać znaki, które mają specjalne znaczenie w wyrażeniach regularnych POSIX, musisz je uciec. Zobacz także: /programming/4024188/php-function-to-escape-mysql-regexp-syntax


3

Akceptowana odpowiedź nie działa poprawnie. Sprawdza tylko miejsce przed i po tekście.

Załóżmy, że masz następującą listę

  • Kurtka
  • Letnia kurtka
  • Kurtka zimowa

Teraz, jeśli spróbujesz wyszukać kurtkę przy użyciu zaakceptowanej odpowiedzi, zwróci tylko letnią kurtkę i zimową kurtkę

Myślę, że następujące rozwiązanie jest lepsze

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

Nie obejmuje przypadku (c) z pytania (tj. Również pasuje do „kurtki”). Zamiast tego można dodać czwarty warunek, ['eq' => $needle]aby znaleźć dokładne dopasowania (lub lepiej, użyj rozwiązania wyrażenia regularnego, które znajduje wszystkie granice, nie tylko spacje)
Fabian Schmengler

powyższy kod jest w stanie znaleźć dokładne dopasowania. Sprawdziłem to
Dinesh Yadav

Nie wątpiłem w to. Ale znajduje więcej, czego nie powinien. Przynajmniej jeśli masz takie same wymagania jak w pierwotnym pytaniu: nie znajdź „foo barer” podczas wyszukiwania „foo bar”
Fabian Schmengler

Tak masz rację. Przyjęta odpowiedź nie działała dla mnie poprawnie, więc zasugerowałem prosty filtr jednowierszowy, aby uzyskać podobne pozycje.
Dinesh Yadav
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.