Search query builder library
It aims to split complex searching queries
into small classes
Framework-agnostic
Database-agnostic
Agnostic as much as possible
Can I use it with framework X?
Can I use it with database Y?
Some searching contexts areÂ
already implemented:
If you need more - just implement it. It's really easy
Doctrine ORM
MongoDB
Elastica
Symfony's Finder
It will enforce developers
to think about
splitting complex queries
with a lot of constraints
It will help you to create
small and
easily-testable
cirteria builders
with single responsibility
You can use it to create
chain searching process
in which results of first search can be
transformed into criteria of next search
Search #1
Search #2
Each of sub-searches may use completely different database
Supported PHP versions
PHP 5.4
PHP 5.5
PHP 5.6
PHP 7.0
PHP 7.1
HHVM
Travis CI
Scrutinizer
are inspecting each pull request
SensioLabsInsights
Style CI
Full documentation is always available by ReadTheDocs.org
It is well tested with help of
PHPUnit
PHPUnit 4.8.10 by Sebastian Bergmann and contributors.
............................................................... 63 / 194 ( 32%)
............................................................... 126 / 194 ( 64%)
............................................................... 189 / 194 ( 97%)
.....
Time: 830 ms, Memory: 8.00Mb
OK (194 tests, 281 assertions)
It is well tested with help of
Humbug
Tests: 194 Line Coverage: 100.00%
Humbug is analysing source files...
Mutation Testing is commencing on 46 files...
(.: killed, M: escaped, S: uncovered, E: fatal error, T: timed out)
.........................................................
57 mutations were generated:
57 mutants were killed
0 mutants were not covered by tests
0 covered mutants were not detected
0 fatal errors were encountered
0 time outs were encountered
Metrics:
Mutation Score Indicator (MSI): 100%
Mutation Code Coverage: 100%
Covered Code MSI: 100%
Completely Open Sourced
Following PSR-2
Following semantic versioning
Installable via composer and packagist
All pull-requests and ideas are most welcome
Parameters
Results
Big
repository
method
Parameters
Results
Criteria
Criteria
Criteria
Criteria builder
Criteria builder
Criteria builder
Only applicable criteria goes to builders
Multiple criteria are already implemented
Abstract criteria builders are already implemented
Small classes
Testable
Easy to read
Easy to understand
k_gzocha_searcher:
contexts:
people:
context:
service: my_database_searching_context
criteria:
- { class: \AgeRangeCriteria, name: ageRange }
- { class: \TitleCriteria, name: title }
- { class: \GenderCriteria, name: gender }
- { class: \AlwaysApplicableCriteria, name: onlyAlive }
builders:
- { class: \AgeRangeCriteriaBuilder, name: ageRange }
- { class: \TitleCriteriaBuilder, name: title }
- { class: \GenderCriteriaBuilder, name: gender }
- { class: \OnlyAliveCriteriaBuilder, name: onlyAlive }
Object responsible to all required parameter for single "filter".
For filtering by age range you need two parameters: ageMin and ageMax
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()
{
return null !== $this->minimalAge && null !== $this->maximalAge;
}
// Getters, setters, whatever
}
Service, which will accept applicable Criteria as a parameter and will use to add constraint to query builder.
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
) {
return $criteria instanceof AgeRangeCriteria;
}
/**
* You can skip this method if you will extend from AbstractORMCriteriaBuilder.
*/
public function supportsSearchingContext(
SearchingContextInterface $searchingContext
) {
return $searchingContext instanceof QueryBuilderSearchingContext;
}
}
Service that holds actual query builder and knows how to fetch results from it
class FinderSearchingContext extends AbstractSearchingContext
{
/**
* @param $finder Finder
*/
public function __construct(Finder $finder)
{
parent::__construct($finder);
}
/**
* @return Finder
*/
public function getQueryBuilder()
{
return parent::getQueryBuilder();
}
/**
* @return \Iterator
*/
public function getResults()
{
return $this->getQueryBuilder()->getIterator();
}
}
Collect all hydrated criteria
Collect all criteria builders
Build proper searching context
Build Searcher service with them
Pass them to Searcher
$context = new QueryBuilderSearchingContext($queryBuilder);
$builders = new CriteriaBuilderCollection([
new AgeRangeCriteriaBuilder(),
// .. rest of the builders
]);
$criteria = new CriteriaCollection([
new AgeRangeCriteria(20, 25),
// ... rest of hydrated criteria
]);
$searcher = new Searcher($builders, $context);
// Yay, we have our results!
$results = $searcher->search($criteria);
Krzysztof Gzocha