กรองผลลัพธ์โดยใช้ LIKE


16

พิจารณาสตริง "Haystack" ทั้งสามนี้:

ก) foo bar

ข) welcome to foo bar industries

ค) foo barer

และตอนนี้ "เข็ม" ของฉัน:

foo bar

(หึ)

ฉันต้องการให้ตัวกรองของฉันจับคู่เข็มของฉันกับสตริงที่กองหญ้าเป็น & a แต่ไม่ใช่ c ฉันเหนื่อย:

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

แต่ข้างต้นตรงกับ c

ฉันก็ลอง:

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

ด้านบนตรงกับ b.

ความช่วยเหลือใด ๆ ที่ชื่นชมมาก

คำตอบ:


37

ลองทำดูสิว่ามันเหมาะกับ:

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

การส่งพารามิเตอร์ที่สองเป็นอาร์เรย์ของอาร์เรย์จะเชื่อมโยงเงื่อนไขการใช้ OR


ใช้งานได้ดี :) ไม่ทราบเกี่ยวกับเคล็ดลับอาร์เรย์ขอบคุณ
Beingalex

ที่มีรูปแบบที่กำหนดเอง / ไม่ใช่ eav ควรจะเปลี่ยนaddAttributeToFilter addFieldToFilter
jvalanen

มีวิธีการตรวจสอบว่าอาร์เรย์ส่งกลับผลลัพธ์หรือไม่? ฉันใช้วิธีนี้เพื่อค้นหาคอลเลกชันโมเดลที่กำหนดเอง (ชื่อคำอธิบายฟิลด์ Alternate_name) และฉันต้องการที่จะทราบว่าผลลัพธ์ถูกเข้าชมเนื่องจากคำอธิบาย (เพื่อรวมองค์ประกอบ UI เพิ่มเติมในผลการค้นหา)
pspahn

3
@pspahn ไม่ตรงไปข้างหน้าอย่างใดอย่างหนึ่ง คุณสามารถวนซ้ำผลลัพธ์หลังจากการเลือกถูกดำเนินการและตรวจสอบว่ามีเข็มอยู่ในเขตข้อมูลใด ๆ ที่คุณต้องการ
Marius

9

ทางออกที่เป็นไปได้คือการใช้REGEXPแทนLIKE:

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

จากเอกสาร MySQL :

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

เครื่องหมายเหล่านี้หมายถึงขอบเขตของคำ พวกเขาตรงกับจุดเริ่มต้นและจุดสิ้นสุดของคำตามลำดับ คำคือลำดับของอักขระคำที่ไม่ได้นำหน้าหรือตามด้วยอักขระคำ ตัวอักษรคำเป็นตัวอักษรและตัวเลขในคลาส alnum หรือขีดล่าง (_)

โปรดทราบว่าหาก$needleสามารถมีตัวละครที่มีความหมายพิเศษในการแสดงออกปกติ POSIX คุณจะต้องหลบหนีพวกเขา ดูเพิ่มเติมที่: /programming/4024188/php-function-to-escape-mysql-regexp-syntax


3

คำตอบที่ยอมรับนั้นทำงานไม่ถูกต้อง มันตรวจสอบพื้นที่เฉพาะก่อนและหลังข้อความ

สมมติว่าคุณมีรายการต่อไปนี้

  • แจ็คเก็ต
  • แจ็คเก็ตฤดูร้อน
  • แจ็คเก็ตฤดูหนาว

ตอนนี้ถ้าคุณพยายามค้นหาด้วยแจ็คเก็ตโดยใช้คำตอบที่ยอมรับแล้วมันจะส่งคืนเฉพาะแจ็คเก็ตฤดูร้อนและแจ็คเก็ตฤดูหนาว

ฉันคิดว่าทางออกต่อไปนี้ดีกว่า

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

มันจะไม่ครอบคลุมกรณี (c) จากคำถาม (เช่นยังตรงกับ "jacketing") แต่['eq' => $needle]สามารถเพิ่มเงื่อนไขที่สี่เพื่อค้นหาการจับคู่ที่แน่นอน (หรือดีกว่าให้ใช้โซลูชัน regex ซึ่งค้นหาขอบเขตทั้งหมดไม่ใช่เฉพาะที่ว่าง)
Fabian Schmengler

รหัสด้านบนสามารถค้นหาการแข่งขันที่แน่นอน ฉันตรวจสอบแล้ว
Dinesh Yadav

ฉันไม่สงสัยเลยว่า แต่พบมากขึ้นซึ่งไม่ควร อย่างน้อยถ้าคุณมีข้อกำหนดเช่นเดียวกับในคำถามเดิม: อย่าค้นหา "foo barer" เมื่อค้นหา "foo barer"
Fabian Schmengler

ใช่คุณถูก. คำตอบที่ได้รับการยอมรับไม่ทำงานสำหรับฉันอย่างถูกต้องดังนั้นฉันแนะนำตัวกรองแบบบรรทัดเดียวสำหรับการรับไอเท็มในทำนองเดียวกัน
Dinesh Yadav
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.