Filtrar resultados usando LIKE


16

Considere estas tres cadenas de "pajar":

un) foo bar

si) welcome to foo bar industries

C) foo barer

Y ahora mi "aguja":

foo bar

(Je)

Me gustaría que mi filtro haga coincidir mi aguja con las cadenas de pajar a & b pero no c. Yo he tratado:

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

Pero lo anterior coincide con c.

También probé:

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

Lo anterior solo coincide con b.

Cualquier ayuda es muy apreciada.

Respuestas:


37

Intente esto y vea si encaja:

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

Pasar el segundo parámetro como una matriz de matrices concatenará las condiciones usando OR


Eso funciona :) No sabía sobre el truco de la matriz, gracias.
— beingalex

Con modelos personalizados / no eav se addAttributeToFilterdeben reemplazar con addFieldToFilter.
— jvalanen

¿Hay alguna manera de determinar qué matriz devolvió un resultado? Estoy usando este método para buscar en una colección de modelos personalizados (nombre, descripción, campos de nombre alternativo) y me gustaría saber si el resultado se alcanzó debido a la descripción (para incluir un elemento de IU adicional en los resultados de búsqueda).
— pspahn

3
@pspahn No es sencillo. Puede recorrer los resultados después de ejecutar la selección y verificar si la aguja se encuentra en alguno de los campos que desea.
— Marius

9

Una posible solución es usar en REGEXPlugar de LIKE:

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

De la documentación de MySQL :

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

Estos marcadores representan límites de palabras. Coinciden con el principio y el final de las palabras, respectivamente. Una palabra es una secuencia de caracteres de palabras que no está precedida o seguida de caracteres de palabras. Un carácter de palabra es un carácter alfanumérico en la clase alnum o un guión bajo (_).

Tenga en cuenta que si $needlepuede contener caracteres que tienen significados especiales en las expresiones regulares POSIX, debe escapar de ellos. Ver también: /programming/4024188/php-function-to-escape-mysql-regexp-syntax


3

La respuesta aceptada no funciona correctamente. Está comprobando solo el espacio antes y después del texto.

Supongamos que tienes la siguiente lista

  • Chaqueta
  • Chaqueta de verano
  • Chaqueta de invierno

Ahora, si intentas buscar con la chaqueta con la respuesta aceptada, solo se mostrarán Summer Jacket y Winter Jacket

Creo que la siguiente solución es mejor

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

No cubriría el caso (c) de la pregunta (es decir, también coincidiría con "camisa"). En cambio, se ['eq' => $needle]podría agregar una cuarta condición para encontrar coincidencias exactas (o mejor, usar la solución regex que encuentra todos los límites, no solo los espacios)
— Fabian Schmengler

El código anterior puede encontrar las coincidencias exactas. Lo revisé
— Dinesh Yadav

No lo dudo. Pero encuentra más, que no debería. Al menos si tiene los mismos requisitos que en la pregunta original: No encuentre "foo barer" cuando busque "foo bar"
— Fabian Schmengler

Sí, tiene usted razón. La respuesta aceptada no funcionaba correctamente para mí, así que sugerí el filtro simple de una línea para obtener los elementos similares.
— Dinesh Yadav
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.