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.

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


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


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. '%'));

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.