2
2
3
3
# Shared Query Builder
4
4
5
- #### Doctrine 2 query builder decorator - [ AndanteProject] ( https://github.com/andanteproject )
5
+ #### Doctrine 2 [ Query Builder ] ( https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/reference/query- builder.html ) decorator - [ AndanteProject] ( https://github.com/andanteproject )
6
6
7
7
[ ![ Latest Version] ( https://img.shields.io/github/release/andanteproject/shared-query-builder.svg )] ( https://github.com/andanteproject/shared-query-builder/releases )
8
8
![ Github actions] ( https://github.com/andanteproject/shared-query-builder/actions/workflows/workflow.yml/badge.svg?branch=main )
@@ -47,7 +47,7 @@ $ composer require andanteproject/shared-query-builder
47
47
48
48
After creating
49
49
your [ query builder] ( https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/reference/query-builder.html ) , wrap
50
- it inside out SharedQueryBuilder.
50
+ it inside our ` SharedQueryBuilder ` .
51
51
52
52
``` php
53
53
use Andante\Doctrine\ORM\SharedQueryBuilder;
@@ -83,7 +83,7 @@ $qb = $sqb->unwrap();
83
83
84
84
### Entity methods
85
85
86
- You can ask the SharedQueryBuilder if it has and entity in the ` from ` statement or some ` join ` statements.
86
+ You can ask the ` SharedQueryBuilder ` if it has and entity in the ` from ` statement or some ` join ` statements.
87
87
88
88
``` php
89
89
if($sqb->hasEntity(User::class)) // bool returned
@@ -99,15 +99,15 @@ statement or a `join` statement).
99
99
$userAlias = $sqb->getAliasForEntity(User::class); // string 'u' returned
100
100
```
101
101
102
- You can use ` withAlias ` method to smoothly add a condition for that entity:
102
+ You can use ` withAlias ` method to smoothly add a condition for that entity property :
103
103
104
104
``` php
105
105
if($sqb->hasEntity(User::class)) // bool returned
106
106
{
107
107
$sqb
108
108
->andWhere(
109
109
$sqb->expr()->eq(
110
- $sqb->withAlias(User::class, 'email'),
110
+ $sqb->withAlias(User::class, 'email'), // string 'u.email'
111
111
':email_value'
112
112
)
113
113
)
@@ -138,10 +138,12 @@ All query builder `join` methods can be used as usually, but you can also use th
138
138
$sqb->join(/* args */);
139
139
$sqb->innerJoin(/* args */);
140
140
$sqb->leftJoin(/* args */);
141
+
141
142
// Lazy join methods
142
143
$sqb->lazyJoin(/* args */);
143
144
$sqb->lazyInnerJoin(/* args */);
144
145
$sqb->lazyLeftJoin(/* args */);
146
+
145
147
// They works with all the ways you know you can perform joins in Doctrine
146
148
// A: $sqb->lazyJoin('u.address', 'a')
147
149
// or B: $sqb->lazyJoin('Address::class', 'a', Expr\Join::WITH, $sqb->expr()->eq('u.address','a'))
@@ -150,13 +152,14 @@ $sqb->lazyLeftJoin(/* args */);
150
152
By doing this, you are defining a ` join ` statement ** without actually adding it** to your DQL query. It is going to be
151
153
added to your DQL query only when you add ** another condition/dql part** which refers to it. Automagically ✨.
152
154
153
- Based on how much confused you are right now, you can check for [ you do should you need this] ( #why-do-i-need-this )
154
- reasons or [ some examples] ( #examples ) to achieve your "OMG" moment.
155
+ Based on how much confused you are right now, you can check for [ why you should need this] ( #why-do-i-need-this ) or [ some examples] ( #examples ) to achieve your "OMG" revelation moment.
155
156
156
157
## Examples
157
158
158
159
Let's suppose we need to list ` User ` entities but we also have an ** optional filter** to search an user by it's
159
- address ` Building ` name. There is no need to perform any join until we decide to use that filter. We can use ** Laxy
160
+ address ` Building ` name.
161
+
162
+ There is no need to perform any join until we decide to use that filter. We can use ** Laxy
160
163
Join** to achieve this.
161
164
162
165
``` php
@@ -195,7 +198,7 @@ $users = $sqb->getQuery()->getResults();
195
198
// AND b.name = 'Building A'
196
199
```
197
200
198
- You are probably thinking: ** why don't we achieve the same result like this ** ? (keep in mind that avoid to perform
201
+ You are probably thinking: ** why don't we achieve the same result with the following, more common, way ** ? (keep in mind that avoid to perform
199
202
unecessary joins is still a requirement)
200
203
201
204
``` php
207
210
$qb->expr()->eq('u.verifiedEmail', ':verified_email')
208
211
)
209
212
->setParameter('verified_email', true);
213
+
210
214
if(!empty($buildingNameFilter)){
211
215
$qb
212
216
->lazyJoin('u.address', 'a')
@@ -217,6 +221,7 @@ if(!empty($buildingNameFilter)){
217
221
->setParameter('building_name_value', $buildingNameFilter)
218
222
;
219
223
}
224
+
220
225
$users = $qb->getQuery()->getResults(); // Same result as example shown before
221
226
// But this has some down sides further explained
222
227
```
@@ -225,9 +230,9 @@ The code above is perfectly fine if you build this whole query in the **same con
225
230
226
231
- 👍🏻 You are * aware* of the whole query building process;
227
232
- 👍🏻 You are * aware* of which entities are involved;
228
- - 👍🏻 You are * aware* of which alias are defined for each entity;
233
+ - 👍🏻 You are * aware* of which alias are defined for each entity.
229
234
230
- The problems are :
235
+ But you have problems :
231
236
232
237
- 👎🏻 You are mixing query structure definition with optional filtering criteria.
233
238
- 👎🏻 Code is is quickly going to be an unreadable mess.
@@ -291,9 +296,9 @@ class BuildingNameFilter implements FilterInterface
291
296
292
297
** We are committing some multiple sins here! 💀 The context is changed.**
293
298
294
- - 👎🏻 You are * not aware* of the whole query building process. Is the given QueryBuilder even a query on Users ?;
299
+ - 👎🏻 You are * not aware* of the whole query building process. Is the given QueryBuilder even a query on User entity ?;
295
300
- 👎🏻 You are * not aware* of which entities are involved. Which entities are already been joined?;
296
- - 👎🏻 You are * not aware* of which alias are defined for each entity. No way we are calling ` u.address ` by convention
301
+ - 👎🏻 You are * not aware* of which aliases are defined for each entity. No way we are calling ` u.address ` by convention
297
302
🤨;
298
303
- 👎🏻 Our job in this context is just to apply some filter. We * can* change the query by adding some join statements
299
304
but we * should avoid* that. What if another filter also need to perform those joins? Devastating. 😵
@@ -367,11 +372,13 @@ class BuildingNameFilter implements FilterInterface
367
372
```
368
373
369
374
- 👍🏻 No extra join statements executed when there is no need for them;
370
- - 👍🏻 We can discover if the Query Builder is handling Building entities too and then apply our filtering logic;
371
- - 👍🏻 We are not guessing for entity aliases;
372
- - 👍🏻 Our filter class is only responsible of filtering;
375
+ - 👍🏻 We can discover if the Query Builder is handling an Entity and then apply our business logic;
376
+ - 👍🏻 We are not guessing entity aliases;
377
+ - 👍🏻 Our filter class is only responsible for filtering;
373
378
- 👍🏻 There can be multiple filter class handling different criteria on the same entity without having duplicated join
374
379
statements;
375
- - The world is an happier place 💁.
380
+ - The world is a happier place 💁.
381
+
382
+ Give us a ⭐️ if your world is now a happier place too! 💃🏻
376
383
377
384
Built with love ❤️ by [ AndanteProject] ( https://github.com/andanteproject ) team.
0 commit comments