Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by
SymfonyCon Vienna 2024
December 5-6
Worldwide event in English
+35 talks and workshops
  1. Home
  2. Documentation
  3. Bundles
  4. DoctrineBundle
  5. Middlewares

Middlewares

Edit this page

Doctrine DBAL supports middlewares. According to the DBAL documentation:

"A middleware sits in the middle between the wrapper components and the driver"

They allow to decorate the following DBAL classes:

  • Doctrine\DBAL\Driver
  • Doctrine\DBAL\Driver\Connection
  • Doctrine\DBAL\Driver\Statement
  • Doctrine\DBAL\Driver\Result

Symfony, for instance, uses a middleware to harvest the queries executed by the current page and make them available in the profiler.

You can also create your own middleware. This is an example of a (very) simple middleware that prevents database connections with the root user. The first step is to create the middleware:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

namespace App\Middleware;

use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

class PreventRootConnectionMiddleware implements Middleware
{
    public function wrap(Driver $driver): Driver
    {
        return new PreventRootConnectionDriver($driver);
    }
}

As you can see in the wrap method, the principle of a middleware is to decorate Doctrine objects with your own objects bearing the logic you need. Now, the connect method of the driver must be decorated in PreventRootConnectionDriver to prevent connections with the root user:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

namespace App\Middleware;

use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use SensitiveParameter;

final class PreventRootConnectionDriver extends AbstractDriverMiddleware
{
    public function connect(array $params): Connection
    {
        if (isset($params['user']) && $params['user'] === 'root') {
            throw new \LogicException('Connecting to the database with the root user is not allowed.');
        }

        return parent::connect($params);
    }
}

That's all! Connection with the root user is not possible anymore. Note that connect is not the only method you can decorate in a Connection. But thanks to the AbstractDriverMiddleware default implementation, you only need to decorate the methods for which you want to add some logic. Too see a more advanced example with a decoration of the Statement class, you can look at the middleware implementation starting in the class Symfony\Bridge\Doctrine\Middleware\Debug\Middleware of the Doctrine Bridge. Decorating the Result class follows the same principle.

The middleware we've just created applies by default to all the connections. If your application has several dbal connections, you can limit the middleware scope to a subset of connections thanks to the AsMiddleware PHP attribute. Let's limit our middleware to a connection named legacy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Middleware;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsMiddleware;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

#[AsMiddleware(connections: ['legacy'])]
class PreventRootConnectionMiddleware implements Middleware
{
    public function wrap(Driver $driver): Driver
    {
        return new PreventRootConnectionDriver($driver);
    }
}

If you register multiple middlewares in your application, they will be executed in the order they were registered. If some middleware needs to be executed before another, you can set priority through the AsMiddleware PHP attribute. This priority can be any integer, positive or negative. The higher the priority, the earlier the middleware is executed. If no priority is defined, the priority is considered 0. Let's make sure our middleware is the first middleware executed, so that we don't set up debugging or logging if the connection will be prevented:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Middleware;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsMiddleware;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

#[AsMiddleware(priority: 10)]
class PreventRootConnectionMiddleware implements Middleware
{
    public function wrap(Driver $driver): Driver
    {
        return new PreventRootConnectionDriver($driver);
    }
}

priority and connections can be used together to restrict a middleware to a specific connection while changing its priority.

All the examples presented above assume autoconfigure is enabled. If autoconfigure is disabled, the doctrine.middleware tag must be added to the middleware. This tag supports a connections attribute to limit the scope of the middleware and a priority attribute to change the execution order of the registered middlewares.

Note

Middlewares have been introduced in version 3.2 of doctrine/dbal and at least the 2.6 version of doctrine/doctrine-bundle is needed to integrate them in Symfony as shown above.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    Check Code Performance in Dev, Test, Staging & Production

    Check Code Performance in Dev, Test, Staging & Production

    No stress: we've got you covered with our 116 automated quality checks of your code

    No stress: we've got you covered with our 116 automated quality checks of your code

    Version:

    Symfony footer

    Avatar of iarro, a Symfony contributor

    Thanks iarro for being a Symfony contributor

    1 commit • 6 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • What is Symfony?
      • Symfony at a Glance
      • Symfony Components
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • Symfony Community
      • SymfonyConnect
      • Events & Meetups
      • Projects using Symfony
      • Contributors
      • Symfony Jobs
      • Backers
      • Code of Conduct
      • Downloads Stats
      • Support
    • Blog

      • All Blog Posts
      • A Week of Symfony
      • Case Studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Living on the edge
      • Releases
      • Security Advisories
      • Symfony Insight
      • Twig
      • SensioLabs Blog
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Powered by

    Follow Symfony