Filtrando resultados usando LIKE


16

Considere estas três seqüências de "palheiro":

a) foo bar

b) welcome to foo bar industries

c) foo barer

E agora minha "agulha":

foo bar

(Heh)

Gostaria que meu filtro correspondesse à minha agulha com as cordas do palheiro a & b, mas não c. Eu tentei:

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

Mas o acima corresponde a c.

Eu também tentei:

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

O acima corresponde apenas a b.

Qualquer ajuda é muito apreciada.

Respostas:


37

Faça uma tentativa e veja se ele se encaixa:

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

Passar o segundo parâmetro como uma matriz de matrizes concatenará as condições usando OR


Isso funciona :) Não sabia sobre o truque da matriz, obrigado.
— beingalex

Os modelos personalizados / não eav addAttributeToFilterdevem ser substituídos por addFieldToFilter.
— jvalanen

Existe uma maneira de determinar qual matriz retornou um resultado? Estou usando esse método para pesquisar uma coleção de modelos personalizados (campos de nome, descrição, nome_ alternativo) e gostaria de saber se o resultado foi atingido devido à descrição (para incluir um elemento de interface do usuário adicional nos resultados da pesquisa).
— Pspic

3
@pspahn Não é direto. Você pode percorrer os resultados após a seleção ser executada e verificar se a agulha está em algum dos campos que você deseja.
— Marius

9

Uma solução possível é usar em REGEXPvez de LIKE:

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

Na documentação do MySQL :

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

Esses marcadores representam limites de palavras. Eles correspondem ao começo e ao fim das palavras, respectivamente. Uma palavra é uma sequência de caracteres da palavra que não é precedida ou seguida por caracteres da palavra. Um caractere de palavra é um caractere alfanumérico na classe alnum ou um sublinhado (_).

Observe que se $needlepuder conter caracteres que tenham significados especiais nas expressões regulares do POSIX, será necessário escapá-los. Consulte também: /programming/4024188/php-function-to-escape-mysql-regexp-syntax


3

A resposta aceita não funciona corretamente. Está verificando apenas o espaço antes e depois do texto.

Suponha que você tenha a seguinte lista

  • Jaqueta
  • Jaqueta de verão
  • Jaqueta de inverno

Agora, se você tentar pesquisar com jaqueta usando a resposta aceita, ele retornará apenas jaqueta de verão e jaqueta de inverno

Eu acho que a seguinte solução é melhor

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

Não cobriria o caso (c) da pergunta (ou seja, também corresponderia a "camisa"). Em vez disso, uma quarta condição ['eq' => $needle]poderia ser adicionado para encontrar correspondências exatas (ou melhor, use a solução regex que encontra todos os limites, não só espaços)
— Fabian Schmengler

o código acima é capaz de encontrar as correspondências exatas. Eu verifiquei
— Dinesh Yadav

Eu não duvidei disso. Mas encontra mais, o que não deveria. Pelo menos se você tem os mesmos requisitos que na pergunta original: não encontrar "barer foo" quando procurar "foo bar"
— Fabian Schmengler

Sim você está certo. A resposta aceita não estava funcionando corretamente para mim, então sugeri o filtro de uma linha simples para obter os itens da mesma forma.
— Dinesh Yadav
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.