Filterergebnisse mit LIKE

16

Betrachten Sie diese drei "Heuhaufen" -Strings:

ein) foo bar

b) welcome to foo bar industries

c) foo barer

Und jetzt meine "Nadel":

foo bar

(Heh)

Ich möchte, dass mein Filter meine Nadel mit den Heuhaufen-Saiten a & b, aber nicht mit c in Übereinstimmung bringt. Ich habe versucht:

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

Aber das obige stimmt mit c überein.

Ich habe auch versucht:

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

Das Obige passt nur zu b.

Jede Hilfe wird sehr geschätzt.

beingalex
quelle

Antworten:

37

Probieren Sie es aus und sehen Sie, ob es passt:

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

Wenn Sie den zweiten Parameter als Array von Arrays übergeben, werden die Bedingungen unter Verwendung von verkettet OR

Marius
quelle
Das funktioniert :) Ich wusste nichts über den Array-Trick, danke.
Beingalex
Bei Custom- / Non-EAV-Modellen addAttributeToFiltersollte durch ersetzt werden addFieldToFilter.
Jvalanen
Gibt es eine Möglichkeit zu bestimmen, welches Array ein Ergebnis zurückgegeben hat? Ich verwende diese Methode zum Durchsuchen einer benutzerdefinierten Modellsammlung (Name, Beschreibung, alternative_Namensfelder) und möchte wissen, ob das Ergebnis aufgrund der Beschreibung gefunden wurde (um zusätzliches Benutzeroberflächenelement in die Suchergebnisse aufzunehmen).
Pspahn
3
@ pspahn Kein direkter. Sie können die Ergebnisse durchlaufen, nachdem die Auswahl ausgeführt wurde, und prüfen, ob die Nadel in einem der gewünschten Felder gefunden wurde.
Marius
9

Eine mögliche Lösung besteht darin, REGEXPanstelle von LIKE:

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

Aus der MySQL-Dokumentation :

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

Diese Marker stehen für Wortgrenzen. Sie stimmen mit dem Anfang bzw. dem Ende von Wörtern überein. Ein Wort ist eine Folge von Wortzeichen, denen keine Wortzeichen vorangehen oder folgen. Ein Wortzeichen ist ein alphanumerisches Zeichen in der ALNUM-Klasse oder ein Unterstrich (_).

Beachten Sie, dass Sie $needleZeichen, die in regulären POSIX-Ausdrücken besondere Bedeutungen haben können, maskieren müssen. Siehe auch: /programming/4024188/php-function-to-escape-mysql-regexp-syntax

Fabian Schmengler
quelle
2

Die akzeptierte Antwort funktioniert nicht richtig. Es prüft nur Leerzeichen vor und nach dem Text.

Angenommen, Sie haben folgende Liste

  • Jacke
  • Sommerjacke
  • Winterjacke

Wenn Sie nun versuchen, mit Jacke unter Verwendung der akzeptierten Antwort zu suchen , werden nur Sommerjacke und Winterjacke zurückgegeben

Ich denke, folgende Lösung ist besser

$collection->addAttributeToFilter('name', array('like' => '%' . $needle. '%'));
Dinesh Yadav
quelle
Es würde nicht Fall (c) von der Frage abdecken (dh auch "Ummantelung" entsprechen). Stattdessen könnte eine vierte Bedingung ['eq' => $needle]hinzugefügt werden, um genaue Übereinstimmungen zu finden (oder besser, verwenden Sie die Regex-Lösung, die alle Grenzen findet, nicht nur Leerzeichen)
Fabian Schmengler
Der obige Code kann die genauen Übereinstimmungen finden. Ich habe es überprüft
Dinesh Yadav
Daran habe ich nicht gezweifelt. Aber es findet mehr, was es nicht sollte. Zumindest, wenn Sie die gleichen Anforderungen wie in der ursprünglichen Frage haben: Finden Sie "foo barer" nicht, wenn Sie "foo bar" suchen
Fabian Schmengler
Ja, du hast recht. Die akzeptierte Antwort funktionierte bei mir nicht richtig, daher schlug ich den einfachen Einzeilenfilter vor, um die entsprechenden Elemente zu erhalten.
Dinesh Yadav