Searcher是一個與框架無關的搜尋查詢產生器。搜尋查詢是使用條件編寫的,可以針對 MySQL、MongoDB、ElasticSearch、檔案或您喜歡的任何其他內容執行。最新版本僅支援 PHP 7 。現在也用 Humbug 進行了測試
您是否見過負責根據許多不同標準搜尋某些內容的程式碼?它可能會變得一團糟!假設您有一個包含 20 個欄位的表單,所有這些欄位都會對搜尋條件產生一些影響。將整個表單傳遞給某些服務並讓它在一個地方解析所有內容並不是一個好主意。借助這個庫,您可以將建立查詢條件的責任分配給幾個較小的類別。每個過濾器一類。每個Criteria
一個CriteriaBuilder
。這樣,在CriteriaBuilder
中您只關心一個Criteria
,這使得它更具可讀性和可維護性。您稍後可以使用完全相同的Criteria
進行不同的搜索,使用不同的CriteriaBuilder
甚至不同的SearchingContext
(甚至可以使用不同的資料庫)。借助FinderSearchingContext
您甚至可以使用搜尋器在系統上尋找文件。
完整文件可以在 http://searcher.rtfd.io/ 找到
您可以透過在終端機中輸入以下命令來透過 Composer 安裝該庫:
$ 作曲家需要 krzysztof-gzocha/searcher
與 Symfony 的整合是在SearcherBundle中完成的
CriteriaBuilder
- 將為單一Criteria
新的條件,
Criteria
- 將傳遞給CriteriaBuilder
模型。你只需要以某種方式給它補充水分,這樣它就會有用。 Criteria 內部可以保存多個字段,並且所有(或部分)字段可以在CriteriaBuilder
內部使用,
SearchingContext
- 單一搜尋的上下文。該服務應該知道如何從建構的查詢中獲取結果,並且它包含名為QueryBuilder
的東西,但它可以是任何適合您的服務 - 任何服務。這是搜尋和資料庫之間的抽象層。 Doctrine的ORM、ODM、Elastica、 Files等都有不同的上下文。如果沒有適合您的上下文,您可以實現一個 - 這應該不難,
Searcher
- 保存CriteriaBuilder
的集合並將Criteria
傳遞給適當的CriteriaBuilder
。
假設我們想要搜尋年齡在某個過濾範圍內的人。在此範例中,我們將使用 Doctrine 的 QueryBuilder,因此我們將使用QueryBuilderSearchingContext
並在CriteriaBuidler
中指定它應該僅與DoctrineORMQueryBuilder
交互,但請記住,我們不必僅使用 Doctrine。
首先,我們需要建立AgeRangeCriteria
- 這個類別將保存最小和最大年齡的值。這裡已經實現了預設Criteria
。
class AgeRangeCriteria 實作 CriteriaInterface{private $minimalAge;private $maximalAge;/** * 僅必要的方法。 * 如果將傳回 true,那麼它將被傳遞給某些 CriteriaBuilder(s) */public function shouldBeApplied(): bool{return null !== $this->minimalAge && null !== $this->maximalAge; }// getter、setter,等等}
在第二步驟中,我們要指定該模型應施加的條件。這就是為什麼我們需要創建AgeRangeCriteriaBuilder
類別 AgeRangeCriteriaBuilder 實作 CriteriaBuilderInterface{public function buildCriteria(CriteriaInterface $criteria,SearchingContextInterface $searchingContext) {$searchingContext->getQueryBuilder() ->andWhere('e.age >= :minimalAge') ->andWhere('e.age <= :maximalAge') ->setParameter('minimalAge', $criteria->getMinimalAge()) ->setParameter('maximalAge', $criteria->getMaximalAge()); }公共函數allowsCriteria(CriteriaInterface $criteria): bool{return $criteria instanceof AgeRangeCriteria; }/** * 如果您將從 AbstractORMCriteriaBuilder 擴展,則可以跳過此方法。 */公用函數supportsSearchingContext(SearchingContextInterface $searchingContext): bool{return $searchingContext instanceof QueryBuilderSearchingContext; } }
在接下來的步驟中,我們需要為Criteria
和CriteriaBuidler
建立集合。
$builders = new CriteriaBuilderCollection();$builders->addCriteriaBuilder(new AgeRangeCriteriaBuilder());$builders->addCriteriaBuilder(/** 其餘建構器 */);
$ageRangeCriteria = new AgeRangeCriteria();// 我們必須在搜尋之前填入模型$ageRangeCriteria->setMinimalAge(23);$ageRangeCriteria->setMaximalAge(29);$criteria = new CriteriaCollrite-); ageRangeCriteria);$criteria->addCriteria(/** 其餘標準*/);
現在我們想要建立SearchingContext
並使用來自 Doctrine ORM 的 QueryBuilder 來填充它。
$context = new QueryBuilderSearchingContext($queryBuilder);$searcher = new Searcher($builders, $context);$searcher->search($criteriaCollection); // 是的,我們得到了結果!
如果當您期望可遍歷物件或陣列時 QueryBuilder 傳回null
的可能性很小,那麼您可以使用WrappedResultsSearcher
而不是普通的Searcher
類別。它的行為與Searcher
完全相同,但它會傳回ResultCollection
,它僅適用於陣列或Traversable
,如果結果為null
您的程式碼仍然可以工作。其外觀如下:
$searcher = new WrappedResultsSearcher(new Searcher($builders, $context));$results = $searcher->search($criteriaCollection); // ResultCollectionforeach 的實例 ($results as $result) {// 可以工作!
為了對結果進行排序,您可以使用已經實施的Criteria
。您不需要從頭開始實施它。請記住,您仍然需要為其實作CriteriaBuilder
(此功能仍在開發中)。 假設您想要對結果進行排序,並且需要 CriteriaBuidler 中的值p.id
來執行此操作,但您希望將其顯示為pid
給最終使用者。沒有什麼比這更簡單的了!這是創建 OrderByCriteria 的方法:
$mappedFields = ['pid' => 'p.id', 'valueForUser' => 'valueForBuilder'];$criteria = new MappedOrderByAdapter(new OrderByCriteria('pid'),$mappedFields);// $criteria-ByappedOrder () = 'p.id'// $criteria->getOrderBy() = 'pid'
當然,您不需要使用MappedOrderByAdapter
- 您可以僅使用OrderByCriteria
,但是使用者將確切地知道哪些欄位正在用於排序。
分頁Criteria
也已實現,您不需要執行此操作,但請記住,您仍然需要實作CriteriaBuilder
來利用它並執行實際分頁(此功能正在開發中)。假設您希望允許最終使用者變更頁面,但不允許變更每頁的項目數。您可以使用以下範例程式碼:
$criteria = new ImmutablePaginationAdapter( new PaginationCriteria($page = 1, $itemsPerPage = 50) );// $criteria->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
許可證:麻省理工學院
作者:克日什托夫‧格佐查