简体   繁体   中英

Symfony 3.4 and Doctrine: How can I get the connections defined in config.yml from inside a service using the name of the connection

I have two databases one for production and one for backup purposes. I want to have a service in Symfony, called from a command, that can execute some SQL queries in one of these two databases depending on the name of the connecction passed by the command. The problem is that I don't know how to obtain the DBAL connection using the name of the connection as a parameter.

I use Symfony 3.4.

The config.yml is:

#config.yml
doctrine:
    dbal:
        default_connection: prod
        connections:
        prod:
            driver: '%database_driver1%'
            host: '%database_host1%'
            port: '%database_port1%'
            dbname: '%database_name1%'
            user: '%database_user1%'
            password: '%database_password1%'
            charset: UTF8

        backup:
            driver: '%database_driver2%'
            host: '%database_host2%'
            port: '%database_port2%'
            dbname: '%database_name2%'
            user: '%database_user2%'
            password: '%database_password2%'
            charset: UTF8

Mi idea is having a service like this:

<?php

namespace ErqBundle\Services;

use Doctrine\DBAL\Driver\Connection;

class ProcSQL {

    public function exSQL($conn_name)
    {
        // How to obtain the connection ???? 
        $conn=$this->getDoctrine()->getConnection($conn_name);
        // This doesn't work !!!

        $sql = "SELECT ....";
        $stmt = $conn->query($sql); 
    }

}

But I haven't been able to obtain the connection from a name of connection like "prod" or "backup" (something like: $conn=$this->getDoctrine()->getConnection($conn_name) )

The only way I have made it work is defining again the connection parameters and make the connection like this:

public function exSQL()
{


    $config = new \Doctrine\DBAL\Configuration();

    $connectionParams = array(
        'dbname' => 'dbname',
        'user' => 'user',
        'password' => 'password',
        'host' => 'prod_host',
        'driver' => 'pdo_mysql',
    );
    $conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);


    $sql = "SELECT ...";
    $stmt = $conn->query($sql); 

    while ($row = $stmt->fetch()) {
        var_dump($row);
    }

    // This works !!!


}

Thanks in advance.

You can use dependency injection like this:

use \Doctrine\ORM\EntityManager;
class ProcSQL {
    private $entityManager
    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function exSQL($conn_name)
    {
        $conn = $this->entityManager->getConnection($conn_name);
    }
}

You need to declare your service like this (I don't know if you are using autowiring or not):

ErqBundle\Services\ProcSql:
    class:     ErqBundle\Services\ProcSql
    arguments:
         - '@doctrine.orm.entity_manager'

Thanks to both of you. Thinking in your answers I've tried:

I added:

use \Doctrine\ORM\EntityManager;

and called the Doctrine EntityManager directly in the construct method.

public function __construct(EntityManager $entityManager)
{
    $this->entityManager = $entityManager;
}

public function exSQL($conn_name)
{

    $conn = $this->entityManager->getConnection($conn_name);

    $sql = "SELECT ...";
    $stmt = $conn->query($sql); 

    while ($row = $stmt->fetch()) {
        var_dump($row);
    }   

} 

and it works!!!!!

Thanks a lot!!!

If you have access to doctrine, you can do something like

$this->getDoctrine()->getManager('backup');

But as @AlessandroMinoccheri says, it's better to inject it/them directly.

If you need to inject the default one, just use doctrine.orm.entity_manager , if you need to inject the backup one, use doctrine.orm.backup_entity_manager

The best way in 2023 is to type hint the Connection correctly.

Autowiring multiple Connections

You can autowire different connections by type-hinting your service arguments with the following syntax: Doctrine\DBAL\Connection $Connection. For example, to inject a connection with the name purchase_logs use this:

public function __construct(Connection $connectionNameConnection)
{
    $this->connection = $purchaseLogsConnection;
}

As for your case, this would result in:

private $prodConnection;
private $backupConnection;

public function __construct(Connection $prodConnection, Connection $backupConnection)
{
    $this->prodConnection= $prodConnection;
    $this->backupConnection= $backupConnection;
}

public function exSQL() {
    $conn = $this->prodConnection;
    // $conn = $this->backupConnection;
    
    $sql = 'SELECT * FROM ...';
    $stmt = $conn->prepare($sql);
    $stmt->execute();
}

Documentation: Autowiring multiple Connections

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM