Symfony/Doctrine:如何使 Doctrine 与 Unix 套接字一起工作? [英] Symfony/Doctrine: How to make Doctrine working with Unix socket?

查看:28
本文介绍了Symfony/Doctrine:如何使 Doctrine 与 Unix 套接字一起工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Unix 套接字连接到 PostgreSQL.我认为只有一种方法可以连接到主机上的数据库,但应用程序在 Docker 中(我遵循不容器化非复制数据库的原则).我正在使用带有最新 Doctrine 的 Symfony 4.

I'm trying to connect to PostgreSQL using Unix socket. It's I think only one way to connect to database which is on host, but the application is in Docker (I follow the principle to not containerize not replicated database). I'm using Symfony 4 with latest Doctrine.

我使用 PDO 对原始 PHP 进行了测试,并且可以正常工作.我不知道如何强制 Doctrine 使用 unix socket.

I made a test on raw PHP with PDO, and it works. I don't have idea how to enforce Doctrine to use unix socket.

<?php
$dbh = new PDO('pgsql:host=/var/run/postgresql;user=xxxx;dbname=zzzz;password=yyyy');
$dbh->setAttribute(PDO::ERRMODE_EXCEPTION, true);
var_dump($dbh->errorInfo());

$stmt = $dbh->query('SELECT 1 as dupa;');
$stmt->execute();

var_dump($stmt->fetchAll());

结果如预期:

www-data@ef0f2269b69a:~/html$ php o.php 
array(3) {
  [0]=>
  string(5) "00000"
  [1]=>
  NULL
  [2]=>
  NULL
}
array(1) {
  [0]=>
  array(2) {
    ["dupa"]=>
    int(1)
    [0]=>
    int(1)
  }
}

问题在于我在 Doctrine 中配置的任何内容:

The problem is whatever I configure in Doctrine I get this:

In PDOConnection.php line 27:
                                                                        
  [PDOException (7)]                                                    
  SQLSTATE[08006] [7] could not connect to server: Connection refused   
        Is the server running on host "localhost" (127.0.0.1) and accepting  
        TCP/IP connections on port 5432?                                     
  could not connect to server: Cannot assign requested address          
        Is the server running on host "localhost" (::1) and accepting        
        TCP/IP connections on port 5432?    

我尝试了 Doctrine 的语法,原始 PDO 语法,不知道.有没有可能我的 pdo_pgsql 没有编译 unix socket 支持?

I tried Doctrine's syntax, raw PDO syntax, do not have idea. Is there a possibility that my pdo_pgsql does not have unix socket support compiled?

这是我在 Doctrine 中作为数据库 URL 尝试的:

This is what I tried as database URL in Doctrine:

pdo-pgsql://yyyy:xxxxx@/var/run/postgresql:5432/zzzzz
pgsql:host=/var/run/postgresql;user=xxxx;dbname=zzzz;password=yyyy

推荐答案

在调试 Doctrine 的驱动程序后,我创建了一个不太优雅的解决方案,但它仍然有效,并且可以改进.

After debugging Doctrine's driver I created a not-so-elegant solution, but nevertheless it is working, and can be improved upon.

我不喜欢访问驱动程序本身中的环境变量,但这可能可以改进.

I don't like accessing environment variable in the driver itself, but possibly this can be improved.

doctrine.yaml

doctrine:
    dbal:
        #driver:   %database_driver%
        driver_class: App\Infrastructure\Common\Service\PostgreSQLDoctrineDriver
        host:     %database_host%
        port:     %database_port%
        dbname:   %database_name%
        user:     %database_user%
        password: %database_password%
        #charset:  UTF8

    orm:
        auto_generate_proxy_classes: %kernel.debug%
        auto_mapping: true

PostgreSQLDoctrineDriver.php

<?php declare(strict_types=1);

namespace App\Infrastructure\Common\Service;

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOPgSql\Driver;
use \PDO;
use \PDOException;
use function defined;

/**
 * Driver that connects through pdo_pgsql
 *
 * Forked original PostgreSQL driver, extended to have a possibility to pass raw PDO DSN to be
 * able to connect via Unix socket
 */
class PostgreSQLDoctrineDriver extends Driver
{
    /**
     * {@inheritdoc}
     */
    public function connect(array $params, $username = null, $password = null, array $driverOptions = [])
    {
        try {
            $pdo = new PDOConnection(
                $_SERVER['POSTGRES_DB_PDO_DSN'] ?? '',
                $username,
                $password,
                $driverOptions
            );

            if (defined('PDO::PGSQL_ATTR_DISABLE_PREPARES')
                && (! isset($driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES])
                    || $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] === true
                )
            ) {
                $pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true);
            }

            /* defining client_encoding via SET NAMES to avoid inconsistent DSN support
             * - the 'client_encoding' connection param only works with postgres >= 9.1
             * - passing client_encoding via the 'options' param breaks pgbouncer support
             */
            if (isset($params['charset'])) {
                $pdo->exec('SET NAMES \'' . $params['charset'] . '\'');
            }

            return $pdo;
        } catch (PDOException $e) {
            throw DBALException::driverException($this, $e);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'pdo_pgsql';
    }
}

这篇关于Symfony/Doctrine:如何使 Doctrine 与 Unix 套接字一起工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆