krzysztof-gzocha/searcher
Composer 安装命令:
composer require krzysztof-gzocha/searcher
包简介
Searcher is a framework-agnostic search query builder. Search queries are written using Criterias and can be run against MySQL, MongoDB, ElasticSearch or even files.
README 文档
README
Searcher

What is that?
Searcher is a framework-agnostic search query builder. Search queries are written using criterias and can be run against MySQL, MongoDB, ElasticSearch, files or whatever else you like. Latest version is supporting only PHP 7. Now tested also with Humbug
See this presentation to understand better
Why?
Have you ever seen code responsible for searching for something based on many different criteria? It can become quite a mess!
Imagine you have a form with 20 fields and all of them have some impact on searching conditions.
It's not a great idea to pass a whole form to some service at let it parse everything in one place.
Thanks to this library you can split the responsibility of building query criteria to several smaller classes. One class per filter. One CriteriaBuilder per Criteria.
This way, inside CriteriaBuilder you care only about one Criteria, which makes it a lot more readable and maintanable.
You can later use exactly the same Criteria for different searches, with different CriteriaBuilder and even different SearchingContext which can use even different databases.
You can even use searcher to find files on your system thanks to FinderSearchingContext.
Full documentation
Full documentation can be found at http://searcher.rtfd.io/
Installation
You can install the library via composer by typing in terminal:
$ composer require krzysztof-gzocha/searcher
Integration
Integration with Symfony is done in SearcherBundle
Idea
CriteriaBuilder- will build new conditions for singleCriteria,Criteria- model that will be passed toCriteriaBuilder. You just need to hydrate it somehow, so it will be useful. Criteria can hold multiple fields inside and all (or some) of them might be used insideCriteriaBuilder,SearchingContext- context of single search. This service should know how to fetch results from constructed query and it holds something calledQueryBuilder, but it can be anything that works for you - any service. This is an abstraction layer between search and database. There are different contexts for Doctrine's ORM, ODM, Elastica, Files and so on. If there is no context for you you can implement one - it's shouldn't be hard,Searcher- holds collection ofCriteriaBuilderand will passCriteriato appropriateCriteriaBuilder.
Example
Let's say we want to search for people whose age is in some filtered range.
In this example we will use Doctrine's QueryBuilder, so we will use QueryBuilderSearchingContext and will specify in our CriteriaBuidler that it should interact only with Doctrine\ORM\QueryBuilder, but remember that we do not have to use only Doctrine.
1. Criteria
First of all we would need to create AgeRangeCriteria - the class that will holds values of minimal and maximal age. There are already implemented default Criteria in here.
class AgeRangeCriteria implements CriteriaInterface { private $minimalAge; private $maximalAge; /** * Only required method. * If will return true, then it will be passed to some of the CriteriaBuilder(s) */ public function shouldBeApplied(): bool { return null !== $this->minimalAge && null !== $this->maximalAge; } // getters, setters, whatever }
2. CriteriaBuilder
In second step we would like to specify conditions that should be imposed for this model.
That's why we would need to create AgeRangeCriteriaBuilder
class AgeRangeCriteriaBuilder implements 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()); } public function allowsCriteria( CriteriaInterface $criteria ): bool { return $criteria instanceof AgeRangeCriteria; } /** * You can skip this method if you will extend from AbstractORMCriteriaBuilder. */ public function supportsSearchingContext( SearchingContextInterface $searchingContext ): bool { return $searchingContext instanceof QueryBuilderSearchingContext; } }
3. Collections
In next steps we would need to create collections for both: Criteria and CriteriaBuidler.
$builders = new CriteriaBuilderCollection(); $builders->addCriteriaBuilder(new AgeRangeCriteriaBuilder()); $builders->addCriteriaBuilder(/** rest of builders */);
$ageRangeCriteria = new AgeRangeCriteria(); // We have to populate the model before searching $ageRangeCriteria->setMinimalAge(23); $ageRangeCriteria->setMaximalAge(29); $criteria = new CriteriaCollection(); $criteria->addCriteria($ageRangeCriteria); $criteria->addCriteria(/** rest of criteria */);
4. SearchingContext
Now we would like to create our SearchingContext and populate it with QueryBuilder taken from Doctrine ORM.
$context = new QueryBuilderSearchingContext($queryBuilder); $searcher = new Searcher($builders, $context); $searcher->search($criteriaCollection); // Yay, we have our results!
If there is even small chance that your QueryBuilder will return null when you are expecting traversable object or array then you can use WrappedResultsSearcher instead of normal Searcher class. It will act exactly the same as Searcher, but it will return ResultCollection, which will work only with array or \Traversable and if result will be just null your code will still work. Here is how it will looks like:
$searcher = new WrappedResultsSearcher(new Searcher($builders, $context)); $results = $searcher->search($criteriaCollection); // instance of ResultCollection foreach ($results as $result) { // will work! } foreach ($results->getResults() as $result) { // Since ResultCollection has method getResults() this will also work! }
Order
In order to sort your results you can make use of already implemented Criteria. You don't need to implement it from scratch. Keep in mind that you still need to implement your CriteriaBuilder for it (this feature is still under development). Let's say you want to order your results and you need value p.id in your CriteriaBuidler to do it, but you would like to show it as pid to end-user. Nothing simpler!
This is how you can create OrderByCriteria:
$mappedFields = ['pid' => 'p.id', 'valueForUser' => 'valueForBuilder']; $criteria = new MappedOrderByAdapter( new OrderByCriteria('pid'), $mappedFields ); // $criteria->getMappedOrderBy() = 'p.id' // $criteria->getOrderBy() = 'pid'
Of course you don't need to use MappedOrderByAdapter - you can use just OrderByCriteria, but then user will know exactly what fields are beeing used to sort.
Pagination
Criteria for pagination is also implemented and you don't need to do it, but keep in mind that you still need to implement CriteriaBuilder that will make use of it and do actual pagination (this feature is under development).
Let's say you want to allow your end-user to change pages, but not number of items per page.
You can use this example code:
$criteria = new ImmutablePaginationAdapter( new PaginationCriteria($page = 1, $itemsPerPage = 50) ); // $criteria->setItemsPerPage(250); <- user can try to change it // $criteria->getItemsPerPage() = 50 <- but he can't actualy do it // $criteria->getPage() = 1
Of course if you want to allow user to change number of items per page also you can skip the ImmutablePaginationAdapter and use just PaginationCriteria.
Contributing
All ideas and pull requests are welcomed and appreciated :) If you have any problem with usage don't hesitate to create an issue, we can figure your problem out together.
Development
Command to run test: composer test.
All unit tests are tested with padric/humbug library for mutation testing,
aiming to keep Mutation Score Indicator equal or close to 100%.
To run mutation tests you need to install humbug and run: humbug in main directory.
Output should be stored in humbuglog.txt.
Thanks to
In alphabetical order
- https://github.com/chkris
- https://github.com/pawelhertman
- https://github.com/ustrugany
- https://github.com/wojciech-olszewski
License
krzysztof-gzocha/searcher 适用场景与选型建议
krzysztof-gzocha/searcher 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 61.75k 次下载、GitHub Stars 达 117, 最近一次更新时间为 2016 年 02 月 04 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「search」 「doctrine」 「query」 「mongo」 「builder」 「elastic」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 krzysztof-gzocha/searcher 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 krzysztof-gzocha/searcher 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 krzysztof-gzocha/searcher 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A Laravel package to retrieve data from Google Search Console
Indexed Search Autocomplete - Extends the TYPO3 Core Extension Indexed_Search searchform with an autocomplete feature.
Query filtering in your frontend
Abstraction Layer to index and search entities
Anax Database Active Record module for model classes.
Make pimcore migration simple
统计信息
- 总下载量: 61.75k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 118
- 点击次数: 11
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2016-02-04