Das Paket ComplexQuery Brandbox\Query stellt Funktionen zur Verfügung, die es ermöglichen, mit Doctrine wirtschaftlich und komplex zu arbeiten.
Erstellen
...
einer Abfrage
Um einen eine Abfrage mit dem Doctrine Query Builder zu erstellen, verwenden wir den Doctrine QueryBuilder. Er wird vom ComplexQuery\Builder
instanziiert und bereitgestellt:beginnen wir mit der Instanziierung des Query\Builder
. Dieser stellt die erforderlichen Werkzeuge bereit, um den Query zu konstruieren und zu verarbeiten. Zunächst wird ein spezifischer Builder für die jeweilige Abfrage-Art erstellt, in diesem Beispiel GroupArticle
. Dieser spezialisierte Builder enthält dann die Logik und die Struktur der eigentlichen Abfrage. Die Verwendung eines spezifischen Builders ermöglicht eine präzise und übersichtliche Gestaltung der Abfrage, die auf den jeweiligen Anwendungsfall zugeschnitten ist.
Codeblock | ||
---|---|---|
| ||
use Brandbox\Framework\Brandbox\ComplexQueryQuery; $groupArticleBuilder$groupArticle = new Demo\Lib\ComplexQueryQuery\GroupArticleBuilderGroupArticle(); $builder = new ComplexQueryQuery\Builder(); $result = $builder->getIterable($groupArticleBuilder); |
Für jeden Query für wird zu diesem Zweck ein eigener Builder erstellt , der den eigentlichen Query für den jeweiligen Fall beinhaltet:
Codeblock | ||
---|---|---|
| ||
use Brandbox\Framework\Brandbox\ComplexQueryQuery; use Brandbox\ShopCore\Shop\Group; use Brandbox\ShopCore\Shop\Article; class GroupArticleBuilderGroupArticle extends ComplexQueryQuery\BuilderAbstractQueryAbstract implements ComplexQueryQuery\BuilderInterfaceQueryInterface { public function build(): void { $this ->select( CQDemoDemo\Lib\Dto\GroupArticle::class, [ 'shopGroup.shopGroupName', 'shopArticle.shopArticleName' ] ) ->from(Group\lib\entity\shopGroup::class) ->joinRelation(Group\lib\entity\shopGroup::class, Article\lib\entity\shopArticle::class) ->joinTranslation( Article\lib\entity\shopArticle::class, Article\lib\entity\translationShopArticle::class, $collationId = 2 ) ->andWhere('translationShopArticle.shopArticleName != \'\'') ->andWhere('shopArticle.shopArticleName LIKE :name') ->orderAsc('shopGroup.shopGroupName') ->orderDesc('shopArticle.shopArticleName') ->noCacheable() ->setFirstResult(0) ->setMaxResults(3) ->setParameter('name', '%Craft%') ; } } |
...
Das vorherige Beispiel zeigt einige konkrete Anwendungsfälle, die nachfolgend beschrieben werden.
Verwenden von DTOs (Data Transfer Objects)
In Innerhalb der SELECT-Anweisung des Builder wird ein DTO referenziert. Der Konstruktur des DTO erwartet zwei Parameter, die dort im zweiten Parameter definiert werden.Builders referenzieren wir ein DTO (Data Transfer Object). Ein DTO dient in diesem Kontext als Struktur, um Daten effizient zwischen verschiedenen Schichten unserer Anwendung zu transportieren. Der Konstruktor des DTOs erwartet spezifische Parameter, die in der SELECT-Anweisung definiert werden. Durch die Verwendung eines DTOs in der Abfrage können wir sicherstellen, dass nur die relevanten Daten übertragen werden, was die Leistung optimiert und die Klarheit der Datenstruktur erhöht.
Codeblock | ||
---|---|---|
| ||
use Brandbox\Attributes\TableIndex; use Brandbox\ShopCore\Shop\Article; #[TableIndex( entityClass: Article\lib\entity\shopArticle::class, columns: ['shop_article_name'], name: 'dtoGroupArticle') ] readonly class GroupArticle { public function __construct( public ?string $groupName = null, public ?string $articleName = null ) { } } |
Joins von Relations
Das DTO enthält zwei Informationen aus je einer Tabelle. Es ist hier also sehr einfach möglich zwischen zwei Tabellen zu Joinen und die Inhalte zusammenzuführen. Dabei ist In unserem Fall enthält das DTO Informationen aus zwei verschiedenen Tabellen. Dies ermöglicht es uns, einen Join zwischen diesen Tabellen durchzuführen und ihre Inhalte zu kombinieren. Es ist wichtig, dabei zu beachten, dass die beiden beteiligten Datentypen auch tatsächlich als Relation existierentatsächlich in einer relationalen Beziehung zueinander stehen. Durch diesen Ansatz können wir komplexe Datenstrukturen effizient abbilden und verarbeiten.
Joins von Translations
Das Gleiche gilt für Ähnlich verhält es sich mit Übersetzungen. Im oben gezeigten Beispiel werden Übersetzungen des Artikel bezogen, die dann aber nicht weiter verarbeitet werdenvorgestellten Beispiel ziehen wir Übersetzungen für Artikel heran. Diese werden dann in die Abfrage integriert, um mehrsprachige Inhalte effektiv zu handhaben. Der Join von Übersetzungen ist besonders nützlich in Systemen, die mehrere Sprachversionen unterstützen, und ermöglicht eine flexible und umfassende Datenabfrage.
Iterable
Im Gegensatz zur Methode getResult() verarbeitet getIterable() die Inhalte Zeilenweise. Das hat sehr deutliche Auswirkungen auf die Performance und den Ressourcenbedarf zur Laufzeit (CPU/RAM).
Individuelle Indizes
Es kann nun der Fall eintreten, dass man für den jeweiligen Query einen bzw. mehrere eigenständige(n) SQL-Index/-Indizes benötigt. Die Indizes können direkt beim DTO ergänzt werden.
Mandanten, Rollen und Rechte
Um diese Ebenen muss man sich auch hier nicht aktiv kümmern. Mandanten, Rollen und Rechte werden in der FROM-Anweisung verarbeitet. Dort ist es möglich anzugeben, ob die jeweiligen Daten verarbeitet werden sollen.