使用PDO(PHP)连接PostgreSQL不稳定

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

Docker下,数据库和PHP项目是分开部署的。

项目中目前有1个端点和1个迁移。

docker-compose.yaml

version: '3.9'

  user_service:
    build:
      context: ./user_service
    container_name: user_service
    ports:
      - "8082:80"  # Map container port 80 to host port 8082
    depends_on:
      - user_db  # Ensure user_db is up before starting this service
    volumes:
      - ./user_service:/var/www/html

  user_db:
    image: postgres:13
    container_name: user_db
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=root
      - POSTGRES_DB=user
    ports:
      - "5433:5432"  # Expose Postgres database on port 5433
    volumes:
      - user_db_data:/var/lib/postgresql/data 

但是,在一种情况下(在请求期间),与数据库的连接不起作用,而在运行迁移时可以工作。

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use App\Repository\UserRepositoryInterface;
use App\Shared\Container;
use FastRoute\RouteCollector;
use FastRoute\RouteParser\Std as RouteParser;
use FastRoute\DataGenerator\GroupCountBased as DataGenerator;
use function FastRoute\simpleDispatcher;

$router = new RouteCollector(new RouteParser(), new DataGenerator());

try {
    $container = Container::build();
} catch (Exception $e) {
    var_dump($e->getMessage());

    return json_encode(
        [
            'error' => $e->getMessage(),
            'code' => $e->getCode(),
        ]
    );
}

$dispatcher = simpleDispatcher(function(RouteCollector $router) {
    $routeSetup = require __DIR__ . '/../src/Routing/web.php';
    $routeSetup($router);
});

$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];

if (false !== $pos = strpos($uri, '?')) {
    $uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);

switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        http_response_code(404);
        echo '404 Not Found';
        break;

    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        http_response_code(405);
        echo '405 Method Not Allowed';
        break;

    case FastRoute\Dispatcher::FOUND:
        $handler = $routeInfo[1];
        $vars = $routeInfo[2];

        if (is_array($handler) && count($handler) === 2) {
            try {
                $controllerClass = $handler[0];
                echo "Attempting to get controller: " . $controllerClass;
                $controller = $container->get($controllerClass);
            } catch (Exception $e) {
                echo "Failed to resolve controller: " . $controllerClass;
                echo "Error: " . $e->getMessage();
                exit;
            }
            if (method_exists($controller, $handler[1])) {
                $response = call_user_func_array([$controller, $handler[1]], $vars);
                echo $response;
            } else {
                echo 'Method not found: ' . $handler[1];
            }
        } else {
            echo 'Handler not callable';
        }
        break;
}

当代码执行到 $controller = $container->get($controllerClass); 时发生错误在index.php/bootstrap.php中。这是错误消息:

“尝试获取控制器:App\Controller\UserController” “无法解析控制器:App\Controller\UserController” “错误:SQLSTATE[08006] [7] 连接到位于“127.0.0.1”的服务器,端口 5433 失败:连接被拒绝。服务器是否在该主机上运行并接受 TCP/IP 连接?” 这是web.php

<?php

use App\Controller\UserController;
use FastRoute\RouteCollector;

return function (RouteCollector $router) {
    $router->addRoute('GET', '/', [UserController::class, 'index']);
    $router->addRoute('POST', '/create-user', [UserController::class, 'createUser']);
};

这是数据库连接

<?php

$host = getenv('POSTGRES_HOST') ?: '127.0.0.1';
$port = getenv('POSTGRES_PORT') ?: '5433';
$dbname = getenv('POSTGRES_DB') ?: 'user';
$user = getenv('POSTGRES_USER') ?: 'root';
$password = getenv('POSTGRES_PASSWORD') ?: 'root';
$charset = 'utf8mb4';

return [
    'host'     => $host,
    'port'     => $port,
    'dbname'   => $dbname,
    'user'     => $user,
    'password' => $password,
    'charset'  => $charset,
];

<?php

namespace App\Shared;

use App\Repository\UserRepository;
use App\Repository\UserRepositoryInterface;
use DI\ContainerBuilder;
use PDO;
use PDOException;

class Container
{
    /**
     * @return \DI\Container
     *
     * @throws \Exception
     */
    public static function build(): \DI\Container
    {
        $containerBuilder = new ContainerBuilder();

        $config = include __DIR__ . '/../../config/database.php';

        try {
            $containerBuilder->addDefinitions([
                PDO::class => function () use ($config) {
                    $dsn = "pgsql:host={$config['host']};port={$config['port']};dbname={$config['dbname']}";
                    return new PDO($dsn, $config['user'], $config['password']);
                },
                UserRepositoryInterface::class => function ($c) {
                    return new UserRepository($c->get(PDO::class));
                }
            ]);
        } catch (PDOException $e) {
            echo "Connection failed: " . $e->getMessage();
            die();
        }

        return $containerBuilder->build();
    }
}

这是连接正常时的迁移案例

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use App\Shared\Container;

try {
    $container = Container::build();
    $pdo = $container->get(PDO::class);

    $sql = "ALTER TABLE app_user
                ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;";

    $pdo->exec($sql);
...
php sql postgresql docker plpgsql
1个回答
0
投票

你必须配置posgresql配置文件;

将此行添加到 pg_hba.conf

host  all  all 0.0.0.0/0 md5

你也可以像这样在docker中为psql定义特定的配置文件;

command: -c config_file=/etc/postgresql.conf
© www.soinside.com 2019 - 2024. All rights reserved.