Download the PHP package mediagone/doctrine-specifications without Composer

On this page you can find all versions of the php package mediagone/doctrine-specifications. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package doctrine-specifications

Doctrine specifications

Latest Version on Packagist Total Downloads

You probably already ended up with cluttered repositories or duplicated criteria, making it difficult to compose or maintain your queries.

But what if your queries were looking like this?

Or also:

If you like it, you probably need this package ;)

Combinations of criteria are unlimited, without any code duplication. \ It will also make hydration of custom read models (DTOs) a breeze.

Summary

  1. Introduction
  2. Example of usage
  3. Extended usages
    1. Return formats
    2. Joins
    3. Read models
    4. Using multiple Entity Managers
    5. Command bus
  4. Generic specifications
    1. Select specifications
    2. Filter specifications
    3. Additional specifications
    4. Debug specifications
  5. Naming and organizing specifications

Installation

This package requires PHP 7.4+ and Doctrine ORM 2.7+

Add it as Composer dependency:

Introduction

The classic Repository pattern (a single class per entity with several methods, one per query) quickly shows its limitations as it grows toward a big messy class.

Using Query Functions partially solves the problem by splitting up queries into separate classes, but you might still get a lot of code duplication. Things get worse if query criteria can be combined arbitrarily, which may result in the creation of an exponential number of classes.

The _Specifications pattern_ comes to the rescue helping you to split them into explicit and reusable filters, improving useability and testability of your database queries. This package is a customized flavor of this pattern (for purists), inspired by Benjamin Eberlei's article. It revolves around a simple concept: specifications. \ Each specification defines a set of criteria that will be automatically applied to Doctrine's QueryBuilder and Query objects, with the help of two methods:

Specifications can be freely combined to build complex queries, while remaining easily testable and maintainable separately.

Example of usage

We'll learn together how to create the following query:

Each method splits the query into separate "specifications":

It will result in this clean query class:

We'll now explain step by step how to build this class:

SpecificationCompound class

First, we need to create our main class that will be updated later in our example. It extends SpecificationCompound which provides a simple specification registration mechanism, we'll see that in details right after.

We'll use a static factory method asEntity() to build our query object and define its return type. Here we want to get back results as entities, but we could hydrate instead a read model (DTO) (eg. asModel()) or return a scalar value (eg. asCount()).

Notes:

SelectArticleEntity specification

Our first specification defines the selected entity in our query builder by overloading the modifyBuilder method:

Let's register it in our specification compound:

This is how we create a custom specification, but having to create a new class for each criterion is really cumbersome. Hopefully, the library provides many generic specifications you can reuse for common usages (see the Generic specifications section below).

So, we can replace our custom specification by the generic one:

Filtering specifications

Our second specification will filter articles by author:

Add it in the compound but this time using a fluent instance method:

Again, a generic specification exists, but this time you can use the following helper method to do that without using addSpecification() (the method uses it internally):

Now we can do exactly the same for our two last filters: orderedAlphabetically and maxCount:

Execute the query

Finally, we can easily retrieve results according to our specification compound, by using the SpecificationRepository class (which fully replaces traditional Doctrine repositories):

Notes:

Extended usages

Return formats

The package allows results to get retrieved in different formats:

Thereby, you can use the same specifications for different result types by adding multiple static factory methods in a compound.

Exemple of usage:

Joins

You can define query joins very easily by adding them in the static constructor. \

Note that the join will be applied to all your queries. \ But if you want to join only on demand, you can define it only for a given specification:

Joins using the same alias are only added once:

Read models

Retrieving data through dedicated classes, instead of entities might be very powerful (if we don't need to update the entity), because it speeds up complex queries (it limits the number of hydrated objects) and allows to flatten relations.

Let's take these two basic entities:

The normal way to get an Article with the name of it's category would be to query the entity and the related Category entity. But it leads to both objects hydration, and potentially multiple queries (depending on the fetch mode used).

Helpfully, Doctrine offers a way to hydrate custom classes by using the NEW operator (see official documentation).

Keeping in sync the query's selected fields and the DTO's constructor's parameters might be tedious, that's why the package also provides an interface to handle everything for you:

Selecting a Read Model in place of an Entity is very straightforward by registering a SelectReadModel specification in the factory method:

The previous asModel method translates to the following DQL:

Using multiple Entity Managers

By default, the default entity manager is used, but you can specify for each Compound which entity manager to use by overloading the getEntityManager method:

You can also get it by the name used in the ORM configuration:

Command bus

Specification queries are best used through a Query bus, that suits very well with DDD, however it's not mandatory. You can easily tweak your own adapter for any bus or another kind of service.

Your query classes might extend SpecificationCompound, making them automatically handleable by a dedicated bus middleware.

If you're looking for a bus package (or just want to see how it's done), you can use mediagone/cqrs-bus which proposes a SpecificationQuery base class and the SpecificationQueryFetcher middleware.

Generic specifications

To remove the hassle of creating custom specifications for most common usages, the library comes with built-in generic specifications. They can be easily registered using the specific compound's protected methods:

Select specifications

Specification name Description
SelectEntity Select and return the entity as query result.
SelectReadModel Select and return a DTO class as query result.
SelectCount Count and return the number of results of the query.
JoinLeft Declare a Left join.
JoinInner Declare an Inner join.
GroupBy Declare a GroupBy clause.
Having Declare a Hanving clause.

Filter specifications

Specifications usable in criteria methods:

Compound method name Specification name QueryBuilder condition
->whereClause(...) WhereClause custom where clause
->whereFieldDifferent(...) WhereFieldDifferent field != value
->whereFieldEqual(...) WhereFieldEqual field = value
->whereFieldGreater(...) WhereFieldGreater field > value
->whereFieldGreaterOrEqual(...) WhereFieldGreaterOrEqual field >= value
->whereFieldLesser(...) WhereFieldLesser field < value
->whereFieldLesserOrEqual(...) WhereFieldLesserOrEqual field <= value
->whereFieldIn(...) WhereFieldIn field IN (value)
->whereFieldNotIn(...) WhereFieldNotIn field NOT IN (value)
->whereFieldInArray(...) WhereFieldInArray field IN (values,generated,list)
->whereFieldNotInArray(...) WhereFieldNotInArray field NOT IN (values,generated,list)
->whereFieldIsNull(...) WhereFieldIsNull field IS NULL
->whereFieldIsNotNull(...) WhereFieldIsNotNull field IS NOT NULL
->whereFieldLike(...) WhereFieldLike field LIKE 'value'
->whereFieldBetween(...) WhereFieldBetween field >= min AND field <= max
->whereFieldBetweenExclusive(...) WhereFieldBetweenExclusive field > min AND field < max
->orderResultsByAsc(...) OrderResultsByAsc ORDER BY expression ASC
->orderResultsByDesc(...) OrderResultsByDesc ORDER BY expression DESC

Example of usage:

Additional specifications

Compound method name Specification name Note
->setParameter(...) SetParameter Define a query builder parameter.
->limitResultsOffset(...) LimitResultsOffset (Pagination) Defines how many results to skip.
->limitResultsMaxCount(...) LimitResultsMaxCount (Pagination) Defines the (max) number of returned results.
->limitResultsPaginate(...) LimitResultsPaginate (Pagination) Combines MaxCount and Offset effects, with different parameters.

Exemple of usage:

A last couple of specifications provide even more flexibility by allowing you to modify the Doctrine QueryBuilder/Query without having to create separate classes:

Compound method name Specification name
->modifyBuilder(...) ModifyBuilder
->modifyQuery(...) ModifyQuery

Debugging specifications

The SpecificationCompound class comes with built-in methods that adds debug oriented specifications to all compound classes, you don't have to include them in your own compounds:

Compound method name Specification name
->dumpDQL(...) DebugDumpDQL
->dumpSQL(...) DebugDumpSQL

So you can easily dump the generated DQL and SQL with few method calls:

Organizing specifications

Naming specifications

Naming convention used in this exemple is only a suggestion, feel free to adapt to your needs or preferences.

There is no hard requirement about naming, but you should use defined prefixes to differentiate between your specifications:

Files organization

You'll probably want to create a separate compound for querying single article (eg. OneArticle) since the specification filters are usually not the same for single or array results (shared specifications can be easily added to both compounds).

Hence a suggested file structure might be:

License

Doctrine Specifications is licensed under MIT license. See LICENSE file.


All versions of doctrine-specifications with dependencies

PHP Build Version
Package Version
Requires php Version ^7.4|^8.0
doctrine/orm Version ^2.7|^3.0
symfony/var-dumper Version ^5.1|^6.0|^7.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package mediagone/doctrine-specifications contains the following files

Loading the files please wait ....