Searcher ist ein Framework-unabhängiger Suchabfrage-Builder. Suchanfragen werden anhand von Kriterien geschrieben und können für MySQL, MongoDB, ElasticSearch, Dateien oder was auch immer Sie möchten ausgeführt werden. Die neueste Version unterstützt nur PHP 7 . Jetzt auch mit Humbug getestet
Haben Sie jemals Code gesehen, der für die Suche nach etwas auf der Grundlage vieler verschiedener Kriterien verantwortlich ist? Es kann ein ziemliches Durcheinander werden! Stellen Sie sich vor, Sie haben ein Formular mit 20 Feldern und alle haben Einfluss auf die Suchbedingungen. Es ist keine gute Idee, ein ganzes Formular an einen Dienst zu übergeben, damit dieser alles an einem Ort analysiert. Dank dieser Bibliothek können Sie die Verantwortung für die Erstellung von Abfragekriterien auf mehrere kleinere Klassen aufteilen. Eine Klasse pro Filter. Ein CriteriaBuilder
pro Criteria
. Auf diese Weise kümmern Sie sich innerhalb CriteriaBuilder
nur um ein Criteria
, wodurch es viel lesbarer und wartbarer wird. Sie können später genau dieselben Criteria
für verschiedene Suchvorgänge verwenden, mit unterschiedlichen CriteriaBuilder
und sogar unterschiedlichem SearchingContext
, der sogar unterschiedliche Datenbanken verwenden kann. Dank FinderSearchingContext
können Sie sogar die Suchfunktion verwenden, um Dateien auf Ihrem System zu finden.
Die vollständige Dokumentation finden Sie unter http://searcher.rtfd.io/
Sie können die Bibliothek über Composer installieren, indem Sie im Terminal Folgendes eingeben:
$ Composer erfordert krzysztof-gzocha/searcher
Die Integration mit Symfony erfolgt in SearcherBundle
CriteriaBuilder
– erstellt neue Bedingungen für einzelne Criteria
,
Criteria
– Modell, das an CriteriaBuilder
übergeben wird. Sie müssen es nur irgendwie mit Feuchtigkeit versorgen, damit es nützlich ist. Kriterien können mehrere Felder enthalten und alle (oder einige) davon können in CriteriaBuilder
verwendet werden.
SearchingContext
– Kontext einer einzelnen Suche. Dieser Dienst sollte in der Lage sein, Ergebnisse aus einer erstellten Abfrage abzurufen, und er enthält etwas namens QueryBuilder
, kann aber alles sein, was für Sie funktioniert – jeder Dienst. Dies ist eine Abstraktionsschicht zwischen Suche und Datenbank. Es gibt verschiedene Kontexte für ORM, ODM, Elastica, Files usw. von Doctrine. Wenn es keinen Kontext für Sie gibt, können Sie einen implementieren – es sollte nicht schwer sein,
Searcher
– enthält eine Sammlung von CriteriaBuilder
und übergibt Criteria
an den entsprechenden CriteriaBuilder
.
Nehmen wir an, wir möchten nach Personen suchen, deren Alter in einem gefilterten Bereich liegt. In diesem Beispiel verwenden wir den QueryBuilder von Doctrine, also verwenden wir QueryBuilderSearchingContext
und geben in unserem CriteriaBuidler
an, dass er nur mit DoctrineORMQueryBuilder
interagieren soll. Denken Sie jedoch daran, dass wir nicht nur Doctrine verwenden müssen.
Zunächst müssten wir AgeRangeCriteria
erstellen – die Klasse, die Werte für das minimale und maximale Alter enthält. Hier sind bereits Criteria
implementiert.
Die Klasse AgeRangeCriteria implementiert CriteriaInterface{private $minimalAge;private $maximalAge;/** * Nur erforderliche Methode. * Wenn „true“ zurückgegeben wird, wird es an einige der CriteriaBuilder(s) übergeben. }// Getter, Setter, was auch immer}
Im zweiten Schritt möchten wir Bedingungen festlegen, die für dieses Modell gelten sollen. Deshalb müssten wir AgeRangeCriteriaBuilder
erstellen
Klasse AgeRangeCriteriaBuilder implementiert 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()); }öffentliche Funktion erlaubtCriteria(CriteriaInterface $criteria): bool{return $criteria exampleof AgeRangeCriteria; }/** * Sie können diese Methode überspringen, wenn Sie von AbstractORMCriteriaBuilder aus erweitern. */public function unterstütztSearchingContext(SearchingContextInterface $searchingContext): bool{return $searchingContext exampleof QueryBuilderSearchingContext; } }
In den nächsten Schritten müssten wir Sammlungen für beide erstellen: Criteria
und CriteriaBuidler
.
$builders = new CriteriaBuilderCollection();$builders->addCriteriaBuilder(new AgeRangeCriteriaBuilder());$builders->addCriteriaBuilder(/** rest of builders */);
$ageRangeCriteria = new AgeRangeCriteria();// Wir müssen das Modell füllen, bevor wir suchen$ageRangeCriteria->setMinimalAge(23);$ageRangeCriteria->setMaximalAge(29);$criteria = new CriteriaCollection();$criteria->addCriteria( $ageRangeCriteria);$criteria->addCriteria(/** Rest der Kriterien */);
Jetzt möchten wir unseren SearchingContext
erstellen und ihn mit QueryBuilder aus Doctrine ORM füllen.
$context = new QueryBuilderSearchingContext($queryBuilder);$searcher = new Searcher($builders, $context);$searcher->search($criteriaCollection); // Juhu, wir haben unsere Ergebnisse!
Wenn auch nur eine geringe Wahrscheinlichkeit besteht, dass Ihr QueryBuilder null
zurückgibt, wenn Sie ein durchquerbares Objekt oder Array erwarten, können Sie WrappedResultsSearcher
anstelle der normalen Searcher
-Klasse verwenden. Es verhält sich genauso wie Searcher
, gibt jedoch ResultCollection
zurück, was nur mit Array oder Traversable
funktioniert. Wenn das Ergebnis nur null
ist, funktioniert Ihr Code weiterhin. So wird es aussehen:
$searcher = new WrappedResultsSearcher(new Searcher($builders, $context));$results = $searcher->search($criteriaCollection); // Instanz von ResultCollectionforeach ($results as $result) {// wird funktionieren!}foreach ($results->getResults() as $result) {// Da ResultCollection die Methode getResults() hat, wird dies auch funktionieren!}
Zur Sortierung Ihrer Ergebnisse können Sie auf bereits implementierte Criteria
zurückgreifen. Sie müssen es nicht von Grund auf implementieren. Beachten Sie, dass Sie dafür noch Ihren CriteriaBuilder
implementieren müssen (diese Funktion befindet sich noch in der Entwicklung). Nehmen wir an, Sie möchten Ihre Ergebnisse ordnen und benötigen dazu den Wert p.id
in Ihrem CriteriaBuidler, möchten ihn aber dem Endbenutzer als pid
anzeigen. Nichts einfacher! So können Sie OrderByCriteria erstellen:
$mappedFields = ['pid' => 'p.id', 'valueForUser' => 'valueForBuilder'];$criteria = new MappedOrderByAdapter(new OrderByCriteria('pid'),$mappedFields);// $criteria->getMappedOrderBy () = 'p.id'// $criteria->getOrderBy() = 'pid'
Natürlich müssen Sie MappedOrderByAdapter
nicht verwenden – Sie können einfach OrderByCriteria
verwenden, aber dann weiß der Benutzer genau, welche Felder zum Sortieren verwendet werden.
Criteria
für die Paginierung sind ebenfalls implementiert und Sie müssen dies nicht tun. Beachten Sie jedoch, dass Sie dennoch CriteriaBuilder
implementieren müssen, der sie nutzt und die tatsächliche Paginierung durchführt (diese Funktion befindet sich in der Entwicklung). Nehmen wir an, Sie möchten Ihrem Endbenutzer erlauben, Seiten zu ändern, aber nicht die Anzahl der Elemente pro Seite. Sie können diesen Beispielcode verwenden:
$criteria = new ImmutablePaginationAdapter( new PaginationCriteria($page = 1, $itemsPerPage = 50) );// $criteria->setItemsPerPage(250); <- Benutzer kann versuchen, es zu ändern// $criteria->getItemsPerPage() = 50 <- aber er kann es nicht wirklich tun// $criteria->getPage() = 1
Wenn Sie dem Benutzer erlauben möchten, die Anzahl der Elemente pro Seite zu ändern, können Sie natürlich auch den ImmutablePaginationAdapter
überspringen und nur PaginationCriteria
verwenden.
Alle Ideen und Pull-Anfragen sind willkommen und werden geschätzt :) Wenn Sie Probleme mit der Nutzung haben, zögern Sie nicht, ein Problem zu erstellen. Wir können Ihr Problem gemeinsam lösen.
Befehl zum Ausführen von Test: composer test
.
Alle Unit-Tests werden mit der Padric/Humbug-Bibliothek für Mutationstests getestet, mit dem Ziel, den Mutation Score Indicator gleich oder nahe 100 % zu halten.
Um Mutationstests durchzuführen, müssen Sie Humbug installieren und Folgendes ausführen: humbug
im Hauptverzeichnis. Die Ausgabe sollte in humbuglog.txt
gespeichert werden.
In alphabetischer Reihenfolge
https://github.com/chkris
https://github.com/pawelhertman
https://github.com/ustrugany
https://github.com/wojciech-olszewski
Lizenz: MIT
Autor: Krzysztof Gzocha