动态学说数据库连接

问题描述 投票:0回答:2

我有一个 symfony 5 下的监控应用程序项目。

目前,我已经使用包含来自另一个应用程序的日志的单个数据库完成了大部分工作。我现在想要做的是能够动态连接到数据库(MSSQL)。 目前与数据库的连接是通过文件“doctrine.yaml”完成的。

Doctrine.yaml

 doctrine:
  dbal:
   default_connection: default
    connections:
     default:
       driver: pdo_sqlsrv
       host: 192.168.1.33
       port: null
       dbname: 'job'
       user: 'sa'
       password: 'Lasernet@2020'
       charset: utf8mb4

   orm:
    default_entity_manager: default
    entity_managers:
     default:
       connection: default
       mappings:
        Main:
         is_bundle: false
         type: annotation
         dir: "%kernel.project_dir%/src/Entity/Main"
         prefix: 'App\Entity\Main'
         alias: default

我这样做是为了动态连接

动态连接.php

<?php

namespace App\Doctrine;


class DynamicConnection {


    public function __construct($dbname,$user,$password,$host,$driver,$port)
    {
        $this->dbname = $dbname;
        $this->user = $user;
        $this->password = $password;
        $this->host = $host;
        $this->driver = $driver;
        $this->port = $port;

    }

    public function changeDatabase(){



        $connectionParams = array(
            'dbname' => $this->dbname,
            'user' => $this->user,
            'password' => $this->password,
            'host' => $this->host,
            'driver' => $this->driver,
            'port' => $this->port
        );

        $conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
    
        if($conn){
            return $conn;
        }else{
            return "no";
        }

    }


    public function getParams()
    {
        $connectionParams = array(
            'driver' => $this->driver,
            'host' => $this->host,
            'port' => $this->port,
            'dbname' => $this->dbname,
            'user' => $this->user,
            'password' => $this->password,
            'charset' => "utf8mb4",
            'driverOptions' => [],
            'defaultTableOptions' => []
        );

        return $connectionParams;
    }

}

在我的控制器中

/**
 * @Route("/testconnection", name="test_connect")
 */
public function testConnection(){


    $dbname = "job";
    $user = "sa";
    $password = "Lasernet@2020";
    $host = "192.168.1.34";
    $driver = "pdo_sqlsrv";
    $port = null;

    $connection = new DynamicConnection($dbname,$user,$password,$host,$driver,$port);
    $params = $connection->getParams();


    $newEm = EntityManager::create($params,$this->em->getConfiguration(), $this->em->getEventManager());


    $job = $newEm->getRepository(Job::class)->findAll();
    dd($job);
        
}

问题在于 findAll() 返回数据库“192.168.1.33”的所有记录,而不是“192.168.1.34”中的记录,后者表现出不同数量的记录。

是否有另一种方法可以动态连接数据库或直接使用JS修改“doctrine.yaml”文件,但我认为这不是最好的解决方案。

如果有人能解决我的问题,让我的 findAll() 返回 192 数据库中的信息 .168.1.34

小精度两个数据库具有相同的表、字段等结构

php sql-server symfony sqlsrv
2个回答
4
投票

我最近遇到了一个非常相似的问题。对我有用的解决方案是包装类。

<?php

declare(strict_types=1);

namespace App\DBAL;

use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;

final class MultiDbConnectionWrapper extends Connection
{
    public function __construct(
        array $params,
        Driver $driver,
        ?Configuration $config = null,
        ?EventManager $eventManager = null
    ) {
        parent::__construct($params, $driver, $config, $eventManager);
    }

    public function selectDatabase(string $dbName): void
    {
        if ($this->isConnected()) {
            $this->close();
        }

        $params = $this->getParams();
        $params['dbname'] = $dbName;
        parent::__construct($params, $this->_driver, $this->_config, $this->_eventManager);
    }
}

如果您想更改数据库主机,请更改

$params['host'] = 'XX.XX.XXX.XXX';

# config/packages/doctrine.yaml
doctrine:
    dbal:
        url: '%env(resolve:DATABASE_URL)%'
        wrapper_class: App\DBAL\MultiDbConnectionWrapper
class ProductController extends AbstractController
{
    private EntityManagerInterface $em;
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }
    public function add(Request $request): JsonResponse
    {
        $connection = $this->em->getConnection();
        if(!$connection instanceof MultiDbConnectionWrapper) {
            throw new \RuntimeException('Wrong connection');
        }

        $databaseName = 'some_db_name';
        $connection->selectDatabase($databaseName);

您可以在此存储库中找到完整的实现


0
投票

你也可能想看

https://www.doctrine-project.org/projects/doctrine-bundle/en/latest/middlewares.html

防止RootConnectionMiddleware.php

<?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);
    }
}

防止RootConnectionDriver.php

<?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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.