Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing connection to database between DBAL and session handler Symfony2

I'm trying to use same connection to my database between session handler and doctrine dbal:

config.yml

framework:
    session:
        handler_id:  session.handler.one_connection_pdo

services.yml

session.handler.one_connection_pdo:
    class:     AppBundle\Session\OneConnectionPdoHandler
    public:    false
    arguments:
        - "@database_connection"
        - []

AppBundle/Session/OneConnectionPdoHandler.php

namespace AppBundle\Session;


use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;

class OneConnectionPdoHandler extends PdoSessionHandler
{

    public function __construct($pdoOrDsn, array $options)
    {
        if ($pdoOrDsn instanceof Connection) {
            $pdoOrDsn = $pdoOrDsn->getWrappedConnection();
        }
        parent::__construct($pdoOrDsn, $options);
    }

}

Everything seems to work when browsing application but I can't update any entity because I get error:

PDOException: There is already an active transaction
at n/a
    in .../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 1176

at PDO->beginTransaction()
    in .../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 1176

at Doctrine\DBAL\Connection->beginTransaction()
    in .../vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 373

at Doctrine\ORM\UnitOfWork->commit(null)
    in .../vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356

at Doctrine\ORM\EntityManager->flush()
    in .../src/AppBundle/Controller/Admin/DistributorsController.php line 66

at AppBundle\Controller\Admin\DistributorsController->editAction(object(Distributor), object(Request))
    in  line 

at call_user_func_array(array(object(DistributorsController), 'editAction'), array(object(Distributor), object(Request)))
    in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 139

at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
    in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 62

at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
    in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 169

at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
    in .../web/app_dev.php line 31

Is there a way to share connection between doctrine dbal and custom pdo handler?

// EDIT

I finally found a solution inside PdoSessionHandler class.

By default PDO handler uses transaction when reading and writing to session. It start transaction on first read() and commit on close(). In between there were some database operation $em->persist($entity); $em->flush() which spawned another transaction which generated error.

Inside PdoSessionHandler class I found that there is a lock_mode option which can be set like this:

session.handler.one_connection_pdo:
    class:     AppBundle\Session\OneConnectionPdoHandler
    public:    false
    arguments:
        - "@database_connection"
        - { lock_mode: 1 }

When lock_mode is set to 1 (PdoSessionHandler::LOCK_ADVISORY) PDO handler will use advisory lock instead of transaction and there will be no more transaction errors.

like image 710
piotrekkr Avatar asked Sep 25 '22 07:09

piotrekkr


1 Answers

In Symfony 3~

in (app\config\config.yml):

framework:
    session:
     handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler

in (app\config\services.yml):

 Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
        arguments:
            - !service { class: PDO, factory: 'database_connection:getWrappedConnection' }
            - {lock_mode: 1 }
like image 104
Mazen Shaheed Avatar answered Sep 28 '22 05:09

Mazen Shaheed