Memfilter hasil menggunakan LIKE

16

Pertimbangkan tiga string "tumpukan jerami" ini:

Sebuah) foo bar

b) welcome to foo bar industries

c) foo barer

Dan sekarang "jarum" saya:

foo bar

(Heh)

Saya ingin filter saya mencocokkan jarum saya dengan string tumpukan jerami a & b tetapi tidak c. Saya telah mencoba:

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

Tetapi hal di atas cocok dengan c.

Saya juga mencoba:

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

Di atas hanya cocok dengan b.

Bantuan apa pun sangat kami hargai.

beingalex
sumber

Jawaban:

37

Cobalah ini dan lihat apakah cocok:

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

Melewati parameter kedua sebagai array array akan menggabungkan kondisi menggunakan OR

Marius
sumber
Itu berhasil :) Tidak tahu tentang trik array, terima kasih.
beingalex
Dengan model custom / non-eav addAttributeToFilterharus diganti dengan addFieldToFilter.
jvalanen
Apakah ada cara untuk menentukan array mana yang mengembalikan hasil? Saya menggunakan metode ini untuk mencari koleksi model khusus (nama, deskripsi, bidang nama alternatif) dan saya ingin tahu apakah hasilnya terkena karena deskripsi (untuk memasukkan elemen UI tambahan pada hasil pencarian).
pspahn
3
@ pspahn Bukan yang lurus ke depan. Anda dapat mengulang hasil setelah pemilihan dijalankan dan memeriksa apakah jarum ditemukan di salah satu bidang yang Anda inginkan.
Marius
9

Solusi yang mungkin adalah menggunakan REGEXPalih-alih LIKE:

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

Dari dokumentasi MySQL :

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

Penanda ini berarti batas kata. Mereka cocok dengan awal dan akhir kata, masing-masing. Kata adalah urutan karakter kata yang tidak didahului oleh atau diikuti oleh karakter kata. Karakter kata adalah karakter alfanumerik di kelas alnum atau garis bawah (_).

Perhatikan bahwa jika $needledapat berisi karakter yang memiliki arti khusus dalam ekspresi reguler POSIX, Anda harus menghindarinya. Lihat juga: /programming/4024188/php-function-to-escape-mysql-regexp-syntax

Fabian Schmengler
sumber
3

Jawaban yang diterima tidak berfungsi dengan baik. Ini hanya memeriksa ruang sebelum dan sesudah teks.

Misalkan, Anda memiliki daftar berikut

  • Jaket
  • Jaket Musim Panas
  • Jaket musim dingin

Sekarang jika Anda mencoba mencari dengan jaket menggunakan jawaban yang diterima, itu akan mengembalikan hanya Jaket Musim Panas dan Jaket Musim Dingin

Saya pikir solusi berikut ini lebih baik

$collection->addAttributeToFilter('name', array('like' => '%' . $needle. '%'));
Dinesh Yadav
sumber
Itu tidak akan mencakup kasus (c) dari pertanyaan (yaitu juga cocok dengan "jaket"). Alih-alih, kondisi keempat ['eq' => $needle]dapat ditambahkan untuk menemukan kecocokan yang tepat (atau lebih baik, gunakan solusi regex yang menemukan semua batas, tidak hanya spasi)
Fabian Schmengler
kode di atas dapat menemukan kecocokan yang tepat. Saya memeriksanya
Dinesh Yadav
Saya tidak meragukannya. Tetapi ia menemukan lebih banyak, yang seharusnya tidak. Setidaknya jika Anda memiliki persyaratan yang sama seperti dalam pertanyaan awal: Jangan temukan "foo barer" saat mencari "foo bar"
Fabian Schmengler
Ya kamu benar. Jawaban yang diterima tidak berfungsi dengan baik sehingga saya menyarankan filter satu baris sederhana untuk mendapatkan item yang sama.
Dinesh Yadav