Searcher เป็นตัวสร้างคำค้นหาที่ไม่เชื่อเรื่องกรอบงาน คำค้นหาเขียนโดยใช้เกณฑ์และสามารถเรียกใช้กับ MySQL, MongoDB, ElasticSearch, ไฟล์หรืออะไรก็ได้ที่คุณต้องการ เวอร์ชันล่าสุดรองรับเฉพาะ PHP 7 เท่านั้น ตอนนี้ทดสอบด้วย Humbug แล้ว
คุณเคยเห็นโค้ดที่รับผิดชอบในการค้นหาบางสิ่งตามเกณฑ์ที่แตกต่างกันมากมายหรือไม่? มันอาจกลายเป็นเรื่องยุ่งวุ่นวายได้! ลองนึกภาพคุณมีแบบฟอร์มที่มี 20 ฟิลด์ และทั้งหมดมีผลกระทบต่อเงื่อนไขการค้นหา ไม่ใช่ความคิดที่ดีที่จะส่งแบบฟอร์มทั้งหมดไปยังบริการบางอย่างโดยปล่อยให้แยกวิเคราะห์ทุกอย่างในที่เดียว ต้องขอบคุณไลบรารีนี้ที่ทำให้คุณสามารถแบ่งความรับผิดชอบในการสร้างเกณฑ์การสืบค้นออกเป็นคลาสเล็กๆ หลายๆ คลาสได้ หนึ่งคลาสต่อตัวกรอง หนึ่ง CriteriaBuilder
ต่อ Criteria
ด้วยวิธีนี้ ภายใน CriteriaBuilder
คุณจะสนใจเพียง Criteria
เดียวเท่านั้น ซึ่งทำให้สามารถอ่านและบำรุงรักษาได้มากขึ้น คุณสามารถใช้ Criteria
เดียวกันทุกประการสำหรับการค้นหาที่แตกต่างกันได้ในภายหลัง โดยมี CriteriaBuilder
ที่แตกต่างกันและแม้แต่ SearchingContext
ที่แตกต่างกันซึ่งสามารถใช้ฐานข้อมูลที่แตกต่างกันได้ คุณสามารถใช้ตัวค้นหาเพื่อค้นหา ไฟล์ ในระบบของคุณด้วย FinderSearchingContext
สามารถดูเอกสารฉบับเต็มได้ที่http://searcher.rtfd.io/
คุณสามารถติดตั้งไลบรารีผ่านผู้แต่งโดยพิมพ์ในเทอร์มินัล:
$ ผู้แต่งต้องการ krzysztof-gzocha/searcher
การบูรณาการกับ Symfony เสร็จสิ้นใน SearcherBundle
CriteriaBuilder
- จะสร้าง เงื่อนไข ใหม่สำหรับ Criteria
เดียว
Criteria
- โมเดลที่จะถูกส่งไปยัง CriteriaBuilder
คุณเพียงแค่ต้องทำให้มันชุ่มชื้นดังนั้นมันจะมีประโยชน์ Criteria สามารถเก็บหลายช่องไว้ภายในและทั้งหมด (หรือบางส่วน) อาจใช้ภายใน CriteriaBuilder
SearchingContext
- บริบทของการค้นหาเดี่ยว บริการนี้ควรรู้วิธีดึงผลลัพธ์จากการสืบค้นที่สร้างขึ้นและมีสิ่งที่เรียกว่า QueryBuilder
แต่อาจเป็นบริการใดก็ได้ที่เหมาะกับคุณ ไม่ว่าจะเป็นบริการใดก็ตาม นี่คือชั้นนามธรรมระหว่างการค้นหาและฐานข้อมูล มีบริบทที่แตกต่างกันสำหรับ ORM, ODM, Elastica, ไฟล์ ของ Doctrine และอื่นๆ หากไม่มีบริบทสำหรับคุณ คุณสามารถนำไปปฏิบัติได้ มันไม่ควรจะยาก
Searcher
- เก็บคอลเลกชันของ CriteriaBuilder
และจะส่งผ่าน Criteria
ไปยัง CriteriaBuilder
ที่เหมาะสม
สมมติว่าเราต้องการค้นหา ผู้ ที่ มีอายุ อยู่ในช่วงที่กรองไว้ ในตัวอย่างนี้ เราจะใช้ QueryBuilder ของ Doctrine ดังนั้นเราจะใช้ QueryBuilderSearchingContext
และจะระบุใน CriteriaBuidler
ของเราว่าควรโต้ตอบกับ DoctrineORMQueryBuilder
เท่านั้น แต่จำไว้ว่าเรา ไม่ ต้องใช้เฉพาะ Doctrine เท่านั้น
ก่อนอื่น เราจะต้องสร้าง AgeRangeCriteria
ซึ่งเป็นคลาสที่จะเก็บค่าอายุขั้นต่ำและอายุสูงสุด มีการนำ Criteria
เริ่มต้นไปใช้แล้วที่นี่
คลาส AgeRangeCriteria ใช้ CriteriaInterface{private $minimalAge;private $maximalAge;/** * เฉพาะวิธีการที่จำเป็นเท่านั้น * ถ้า จะคืนค่าเป็นจริง จากนั้นจะถูกส่งผ่านไปยัง CriteriaBuilder บางส่วน */ฟังก์ชันสาธารณะ shouldBeApplied(): bool{return null !== $this->minimalAge && null !== $this->maximalAge; }// getters, setters, อะไรก็ได้}
ในขั้นตอนที่สอง เราต้องการระบุเงื่อนไขที่ควรกำหนดสำหรับโมเดลนี้ นั่นเป็นเหตุผลที่เราจะต้องสร้าง AgeRangeCriteriaBuilder
คลาส AgeRangeCriteriaBuilder ใช้ CriteriaBuilderInterface{ฟังก์ชันสาธารณะ buildCriteria(CriteriaInterface $criteria,SearchingContextInterface $searchingContext) {$searchingContext->getQueryBuilder() ->และที่ไหน('e.age >= :minimalAge') ->และที่ไหน('e.age <= :maximalAge') ->setParameter('minimalAge', $criteria->getMinimalAge()) ->setParameter('maximalAge', $criteria->getMaximalAge()); } ฟังก์ชั่นสาธารณะอนุญาตให้ Criteria (CriteriaInterface $criteria): บูล {return $criteria instance ของ AgeRangeCriteria; }/** * คุณสามารถข้ามวิธีนี้ได้หากต้องการขยายจาก AbstractORMCriteriaBuilder */ฟังก์ชั่นสาธารณะรองรับSearchingContext(SearchingContextInterface $searchingContext): bool{return $searchingContext instance of QueryBuilderSearchingContext; - -
ในขั้นตอนถัดไป เราจะต้องสร้างคอลเลกชันสำหรับทั้ง: Criteria
และ CriteriaBuidler
$builders = new CriteriaBuilderCollection();$builders->addCriteriaBuilder(new AgeRangeCriteriaBuilder());$builders->addCriteriaBuilder(/** ผู้สร้างที่เหลือ */);
$ageRangeCriteria = new AgeRangeCriteria();// เราต้องเติมโมเดลก่อนที่จะค้นหา$ageRangeCriteria->setMinimalAge(23);$ageRangeCriteria->setMaximalAge(29);$criteria = new CriteriaCollection();$criteria->addCriteria( $ageRangeCriteria);$criteria->addCriteria(/** ส่วนที่เหลือของ เกณฑ์ */);
ตอนนี้เราต้องการสร้าง SearchingContext
ของเราและเติมด้วย QueryBuilder ที่นำมาจาก Doctrine ORM
$context = ใหม่ QueryBuilderSearchingContext($queryBuilder);$searcher = ผู้ค้นหาใหม่($builders, $context);$searcher->ค้นหา($criteriaCollection); // เย้ ผลออกมาแล้ว!
หากมีโอกาสเพียงเล็กน้อยที่ QueryBuilder ของคุณจะส่งคืน null
เมื่อคุณคาดหวังว่าวัตถุหรืออาร์เรย์ที่สามารถผ่านได้ คุณสามารถใช้ WrappedResultsSearcher
แทนคลาส Searcher
ปกติ มันจะทำหน้าที่เหมือนกับ Searcher
ทุกประการ แต่จะส่งคืน ResultCollection
ซึ่งจะใช้ได้กับอาร์เรย์หรือ Traversable
เท่านั้น และหากผลลัพธ์เป็น null
โค้ดของคุณจะยังคงใช้งานได้ นี่คือลักษณะที่ปรากฏ:
$searcher = new WrappedResultsSearcher(ผู้ค้นหาใหม่($builders, $context));$results = $searcher->search($criteriaCollection); // อินสแตนซ์ของ ResultCollectionforeach ($results as $result) {// will work!}foreach ($results->getResults() as $result) {// เนื่องจาก ResultCollection มีเมธอด getResults() สิ่งนี้ก็จะใช้ได้เช่นกัน!}
เพื่อจัดเรียงผลลัพธ์ของคุณ คุณสามารถใช้ Criteria
ที่นำไปใช้แล้วได้ คุณไม่จำเป็นต้องดำเนินการตั้งแต่ต้น โปรดทราบว่าคุณยังคงต้องใช้ CriteriaBuilder
ของคุณ (คุณลักษณะนี้ยังอยู่ระหว่างการพัฒนา) สมมติว่าคุณต้องการเรียงลำดับผลลัพธ์และคุณต้องการค่า p.id
ใน CriteriaBuidler ของคุณจึงจะดำเนินการได้ แต่คุณต้องการแสดงเป็น pid
สำหรับผู้ใช้ปลายทาง ไม่มีอะไรง่ายไปกว่านี้แล้ว! นี่คือวิธีที่คุณสามารถสร้าง OrderByCriteria:
$mappedFields = ['pid' => 'p.id', 'valueForUser' => 'valueForBuilder'];$criteria = ใหม่ MappedOrderByAdapter(OrderByCriteria ใหม่('pid'),$mappedFields);// $criteria->getMappedOrderBy () = 'p.id'// $criteria->getOrderBy() = 'pid'
แน่นอนคุณไม่จำเป็นต้องใช้ MappedOrderByAdapter
- คุณสามารถใช้เพียง OrderByCriteria
ได้ แต่ผู้ใช้จะรู้ได้อย่างชัดเจนว่าฟิลด์ใดที่ใช้ในการเรียงลำดับ
มีการนำ Criteria
สำหรับการแบ่งหน้ามาใช้ด้วย และคุณไม่จำเป็นต้องดำเนินการดังกล่าว แต่โปรดจำไว้ว่าคุณยังต้องใช้ CriteriaBuilder
ที่จะใช้ประโยชน์จากมันและดำเนินการแบ่งหน้าจริง (คุณลักษณะนี้อยู่ระหว่างการพัฒนา) สมมติว่าคุณต้องการอนุญาตให้ผู้ใช้เปลี่ยนหน้า แต่ไม่อนุญาตให้เปลี่ยนจำนวนรายการต่อหน้า คุณสามารถใช้โค้ดตัวอย่างนี้:
$criteria = ใหม่ ImmutablePaginationAdapter( ใหม่ PaginationCriteria($page = 1, $itemsPerPage = 50) );// $เกณฑ์->setItemsPerPage(250); <- ผู้ใช้สามารถลองเปลี่ยนได้// $criteria->getItemsPerPage() = 50 <- แต่เขาทำไม่ได้จริงๆ// $criteria->getPage() = 1
แน่นอนหากคุณต้องการอนุญาตให้ผู้ใช้เปลี่ยนจำนวนรายการต่อหน้าคุณสามารถข้าม ImmutablePaginationAdapter
และใช้เพียง PaginationCriteria
เรายินดีและยินดีรับแนวคิดและคำขอดึงทั้งหมด :) หากคุณมีปัญหาใดๆ เกี่ยวกับการใช้งาน อย่าลังเลที่จะสร้างปัญหา เราสามารถแก้ไขปัญหาของคุณร่วมกัน
คำสั่งให้รันการทดสอบ: composer test
การทดสอบหน่วยทั้งหมดได้รับการทดสอบด้วยไลบรารี Padric/humbug สำหรับการทดสอบการกลายพันธุ์ โดยมีเป้าหมายเพื่อให้ตัวบ่งชี้คะแนนการกลายพันธุ์เท่ากับหรือใกล้เคียง 100%
หากต้องการรันการทดสอบการกลายพันธุ์ คุณต้องติดตั้ง humbug และรัน: humbug
ในไดเร็กทอรีหลัก ควรเก็บเอาต์พุตไว้ใน humbuglog.txt
ตามลำดับตัวอักษร
https://github.com/chkris
https://github.com/pawelhertman
https://github.com/ustrugany
https://github.com/wojciech-olszewski
ใบอนุญาต: เอ็มไอที
ผู้เขียน : คริสตอฟ กโซชา