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.