我有一个 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
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);
您可以在此存储库中找到完整的实现。
你也可能想看
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);
}
}