Download the PHP package andanteproject/shared-query-builder without Composer
On this page you can find all versions of the php package andanteproject/shared-query-builder. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download andanteproject/shared-query-builder
More information about andanteproject/shared-query-builder
Files in andanteproject/shared-query-builder
Package shared-query-builder
Short Description A Doctrine 2 Query Builder decorator that makes easier to build your query in shared contexts
License MIT
Informations about the package shared-query-builder
Shared Query Builder
Doctrine 2 Query Builder decorator - AndanteProject
A Doctrine 2 Query Builder decorator that makes easier to build your query in shared contexts.
Why do I need this?
When your query business logic is big and complex you are probably going to split its building process to different places/classes.
Without SharedQueryBuilder
there is no way to do that unless guessing Entity aliases and messing up with join
statements.
This query builder decorator addresses some problems you can find in a real world situation you usually solve with workarounds and business conventions.
Features
- Ask query builder which alias is used for an entity when you are outside its creation context;
- Lazy joins to declare join statements to be performed only if related criteria are defined;
- Immutable and unique query parameters;
- Works like magic โจ.
Requirements
Doctrine 2 and PHP 7.4.
Install
Via Composer:
Set up
After creating
your query builder, wrap
it inside our SharedQueryBuilder
.
From now on, you can use $sqb
exactly as you usually do
with query builder (every
single method of QueryBuilder
is available on SharedQueryBuilder
), but with some useful extra methods ๐คซ.
When you're done building your query, just unwrap your SharedQueryBuilder
.
Please note:
- The only condition applied to build a
SharedQueryBuilder
is that no join statement has to be declared yet. SharedQueryBuilder
is a decorator ofQueryBuilder
, which means it is not aninstance of QueryBuilder
even if it has all its methods (sadly, Doctrine has no QueryBuilder Interface ๐ฅบ).SharedQueryBuilder
do not allow you to join an Entity multiple times with different aliases.
Which additional methods do I have?
Entity methods
You can ask the SharedQueryBuilder
if it has and entity in the from
statement or some join
statements.
You can ask which is the alias of an Entity inside the query you're building (no matter if it is used in a from
statement or a join
statement).
You can use withAlias
method to smoothly add a condition for that entity property:
Given an alias, you can retrieve its entity class:
QueryBuilder::getAllAliases
is extended to have an optional bool
argument $includeLazy
(default:false
) to
include lazy joins aliases.
Lazy Join
All query builder join
methods can be used as usually, but you can also use them with "lazy
" prefix.
By doing this, you are defining a join
statement without actually adding it to your DQL query. It is going to be
added to your DQL query only when you add another condition/dql part which refers to it. Automagically โจ.
Based on how much confused you are right now, you can check for why you should need this or some examples to achieve your "OMG" revelation moment.
Examples
Let's suppose we need to list User
entities but we also have an optional filter to search an user by it's
address Building
name.
There is no need to perform any join until we decide to use that filter. We can use Laxy Join to achieve this.
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 unecessary joins is still a requirement)
The code above is perfectly fine if you build this whole query in the same context:
- ๐ You are aware of the whole query building process;
- ๐ You are aware of which entities are involved;
- ๐ You are aware of which alias are defined for each entity.
- ๐ You are aware of which query parameters are defined and their purpose.
But you have problems:
- ๐ You are mixing query structure definition with optional filtering criteria.
- ๐ Code is is quickly going to be an unreadable mess.
A real world case
If your query structure grows with lots of joins and filtering criteria, you are probably going to split all that business logic in different classes.
For instance, in a backoffice Users list, you are probably going to define your main query to list entities in your controller and handle optional filters in some other classes.
Filter classes may look like this:
We are committing some multiple sins here! ๐ The context is changed.
- ๐ You are not aware of the whole query building process. Is the given QueryBuilder even a query on User entity?;
- ๐ You are not aware of which entities are involved. Which entities are already been joined?;
- ๐ You are not aware of which aliases are defined for each entity. No way we are calling
u.address
by convention ๐คจ; - ๐ You are aware of what parameters have been defined (
$qb->getParameters()
), but you are not aware why they have been defined, for which purpose and you can also override them changing elsewhere behavior; - ๐ Our job in this context is just to apply some filter. We can change the query by adding some join statements but we should avoid that. What if another filter also need to perform those joins? Devastating. ๐ต
This's why SharedQueryBuilder is going to save your ass in these situations
Let's see how we can solve all these problems with SharedQueryBuilder
(you can now guess why it is named like this).
Using SharedQueryBuilder
you can:
- ๐ Define lazy join to allow them to be performed only if they are needed;
- ๐ Define some parameters immutable to be sure value is not going to be changed elsewhere;
- ๐ You can check if an entity is involved in a query and then apply some business logic;
- ๐ You can ask the query builder which alias is used for a specific entity so you are not going to guess aliases or sharing them between classes using constants (I know you thought of that ๐ง).
Filter classes will look like this:
- ๐ No extra join statements executed when there is no need for them;
- ๐ No way to change/override parameters value once defined;
- ๐ We can discover if the Query Builder is handling an Entity and then apply our business logic;
- ๐ We are not guessing entity aliases;
- ๐ Our filter class is only responsible for filtering;
- ๐ There can be multiple filter class handling different criteria on the same entity without having duplicated join statements;
Immutable Parameters
Shared query builder has Immutable Parameters. Once defined, they cannot be changed otherwise and Exception will be raised.
Set parameter and use it in expression at the same moment
If you are sure you are not going to use a parameter in multiple places inside your query, you can write the following code ๐
this way ๐๐๐
Unique parameters
Beside immutable parameters, you can also demand query builder the generation of a parameter name. Using the following methods, query builder will decorate names to avoid conflicts with already declared ones ( which cannot even happen with immutable parameters).
Conclusion
The world is a happier place ๐.
Give us a โญ๏ธ if your world is now a happier place too! ๐๐ป
Built with love โค๏ธ by AndanteProject team.