Searcher는 프레임워크에 구애받지 않는 검색 쿼리 빌더입니다. 검색 쿼리는 기준을 사용하여 작성되며 MySQL, MongoDB, ElasticSearch, 파일 또는 기타 원하는 항목에 대해 실행할 수 있습니다. 최신 버전은 PHP 7만 지원합니다 . 이제 Humbug로도 테스트되었습니다.
다양한 기준에 따라 무언가를 검색하는 코드를 본 적이 있습니까? 꽤 엉망이 될 수 있어요! 20개의 필드가 있는 양식이 있고 모든 필드가 검색 조건에 어느 정도 영향을 미친다고 가정해 보세요. 한 곳에서 모든 것을 구문 분석하도록 전체 양식을 일부 서비스에 전달하는 것은 좋은 생각이 아닙니다. 이 라이브러리 덕분에 쿼리 기준 작성 책임을 여러 개의 작은 클래스로 나눌 수 있습니다. 필터당 하나의 클래스입니다. Criteria
당 하나의 CriteriaBuilder
. 이렇게 하면 CriteriaBuilder
내에서 하나의 Criteria
에만 관심을 가지게 되어 훨씬 더 읽기 쉽고 유지 관리가 쉬워집니다. 나중에 다른 CriteriaBuilder
및 심지어 다른 데이터베이스를 사용할 수 있는 다른 SearchingContext
사용하여 다른 검색에 대해 정확히 동일한 Criteria
사용할 수 있습니다. FinderSearchingContext
덕분에 검색기를 사용하여 시스템에서 파일을 찾을 수도 있습니다.
전체 문서는 http://searcher.rtfd.io/에서 찾을 수 있습니다.
터미널에 다음을 입력하여 작곡가를 통해 라이브러리를 설치할 수 있습니다.
$ 작곡가는 krzysztof-gzocha/searcher가 필요합니다.
Symfony와의 통합은 SearcherBundle 에서 수행됩니다.
CriteriaBuilder
- 단일 Criteria
에 대한 새로운 조건을 구축합니다.
Criteria
- CriteriaBuilder
에 전달될 모델입니다. 어떻게든 수분을 공급해 주면 유용할 거예요. CriteriaBuilder 내부에는 여러 필드가 포함될 수 있으며 그 중 전부(또는 일부)가 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 중 일부에 전달됩니다. */public 함수 shouldBeApplied(): bool{return null !== $this->minimalAge && null !== $this->maximalAge; }// getter, setter 등 무엇이든}
두 번째 단계에서는 이 모델에 부과되어야 하는 조건을 지정하고 싶습니다. 이것이 바로 AgeRangeCriteriaBuilder
생성해야 하는 이유입니다.
AgeRangeCriteriaBuilder 클래스는 CriteriaBuilderInterface{공용 함수 buildCriteria(CriteriaInterface $criteria,SearchingContextInterface $searchingContext) {$searchingContext->getQueryBuilder()를 구현합니다. ->andWhere('e.나이 >= :minimalAge') ->andWhere('e.나이 <= :maximalAge') ->setParameter('minimalAge', $criteria->getMinimalAge()) ->setParameter('maximalAge', $criteria->getMaximalAge()); }공개 함수 allowedCriteria(CriteriaInterface $criteria): bool{return $criteria 인스턴스of AgeRangeCriteria; }/** * AbstractORMCriteriaBuilder에서 확장하는 경우 이 메서드를 건너뛸 수 있습니다. */공용 함수 지원SearchingContext(SearchingContextInterface $searchingContext): bool{return $searchingContext 인스턴스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
생성하고 Doctrine ORM에서 가져온 QueryBuilder로 채우겠습니다.
$context = 새로운 QueryBuilderSearchingContext($queryBuilder);$searcher = 새로운 검색기($builders, $context);$searcher->search($criteriaCollection); // 네, 결과가 나왔습니다!
탐색 가능한 객체나 배열을 기대할 때 QueryBuilder가 null
반환할 가능성이 조금이라도 있는 경우 일반 Searcher
클래스 대신 WrappedResultsSearcher
사용할 수 있습니다. 이는 Searcher
와 정확히 동일하게 작동하지만 ResultCollection
반환합니다. 이는 배열 또는 Traversable
에서만 작동하며 결과가 null
이면 코드는 계속 작동합니다. 다음과 같이 표시됩니다.
$searcher = 새로운 WrappedResultsSearcher(new Searcher($builders, $context));$results = $searcher->search($criteriaCollection); // ResultCollectionforeach의 인스턴스 ($results as $result) {// 작동합니다!}foreach ($results->getResults() as $result) {// ResultCollection에 getResults() 메소드가 있으므로 이것도 작동합니다!}
결과를 정렬하려면 이미 구현된 Criteria
를 사용할 수 있습니다. 처음부터 구현할 필요는 없습니다. CriteriaBuilder
구현해야 한다는 점을 명심하세요(이 기능은 아직 개발 중입니다). 결과를 정렬하고 이를 수행하려면 CriteriaBuidler에 p.id
값이 필요하지만 이를 최종 사용자에게 pid
로 표시하고 싶다고 가정해 보겠습니다. 더 간단한 것은 없습니다! OrderByCriteria를 생성하는 방법은 다음과 같습니다.
$mappedFields = ['pid' => 'p.id', 'valueForUser' => 'valueForBuilder'];$criteria = new MappedOrderByAdapter(new OrderByCriteria('pid'),$mappedFields);// $criteria->getMappedOrderBy () = 'p.id'// $criteria->getOrderBy() = 'pid'
물론 MappedOrderByAdapter
사용할 필요는 없습니다. OrderByCriteria
만 사용할 수 있지만 사용자는 정렬에 사용되는 필드가 무엇인지 정확히 알 수 있습니다.
페이지 매기기에 대한 Criteria
도 구현되어 있으므로 이를 수행할 필요는 없지만 이를 활용하고 실제 페이지 매기기를 수행하는 CriteriaBuilder
구현해야 한다는 점을 명심하세요(이 기능은 개발 중입니다). 최종 사용자가 페이지를 변경할 수 있도록 허용하지만 페이지당 항목 수는 허용하지 않으려고 한다고 가정해 보겠습니다. 다음 예제 코드를 사용할 수 있습니다.
$criteria = 새로운 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
라이센스: MIT
저자: 크시슈토프 그조차(Krzysztof Gzocha)