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);
...
你必须配置posgresql配置文件;
将此行添加到 pg_hba.conf
host all all 0.0.0.0/0 md5
你也可以像这样在docker中为psql定义特定的配置文件;
command: -c config_file=/etc/postgresql.conf