Конфигурация подключения к БД в PHP: от основ до сложных решений

Раздел: Администрирование PHP -> Конфигурация и настройка PHP

Способы конфигурации подключения к базе данных в PHP

Основное решение: использование PDO с файлом config.php

Современный подход предполагает применение PDO (PHP Data Objects) и хранение параметров подключения в отдельном конфигурационном файле. Файл config.php возвращает массив с настройками, а класс Database обеспечивает единую точку доступа к соединению. Это даёт гибкость, безопасность и удобство тестирования.

Цель: централизованное управление параметрами БД, поддержка разных СУБД, защита от SQL-инъекций через подготовленные запросы.

Пример файла config.php:


<?php
return [
    'driver' => 'mysql',
    'host' => 'localhost',
    'dbname' => 'myapp',
    'username' => 'dbuser',
    'password' => 'secret',
    'charset' => 'utf8mb4',
    'options' => [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ],
];
  

Moodle config php (php: конфигурация moodle (config.php))

Класс-обёртка для подключения:


<?php
class Database
{
    private static ?PDO $instance = null;

    public static function getInstance(): PDO
    {
        if (self::$instance === null) {
            $config = require __DIR__ . '/config.php';
            $dsn = sprintf(
                '%s:host=%s;dbname=%s;charset=%s',
                $config['driver'],
                $config['host'],
                $config['dbname'],
                $config['charset']
            );
            self::$instance = new PDO($dsn, $config['username'], $config['password'], $config['options']);
        }
        return self::$instance;
    }
}
  

Phpmyadmin config inc php (php: конфигурация phpmyadmin (config.inc.php))

Использование:


$pdo = Database::getInstance();
$stmt = $pdo->query('SELECT id, name FROM users');
while ($row = $stmt->fetch()) {
    echo htmlspecialchars($row['name']) . "<br>";
}
  

Config config php домен (php: настройка конфигурации для домена)

Типичная ошибка: "could not find driver"

Возникает, если в системе не установлен драйвер PDO для используемой СУБД (например, pdo_mysql). Решение: установить расширение через менеджер пакетов или php.ini. Для MySQL в Ubuntu: sudo apt install php-mysql, затем перезапустить веб-сервер.

Другая проблема: неверные параметры подключения. Проверка: var_dump($config); убедиться, что массив содержит все ключи.

Как подключиться к базе данных через MySQLi с конфигурационным файлом?

MySQLi – альтернативный расширение с поддержкой процедурного и объектно-ориентированного стиля. Параметры можно хранить в константах или массиве.

Цель: использование, если проект завязан на эксклюзивных функциях MySQLi или требуется работа с асинхронными запросами.


<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_NAME', 'app');
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
// Работа с БД
$mysqli->close();
  

Wp admin config php (php: конфигурация wordpress (wp-admin/config.php))

Вариант с файлом config.php, возвращающим массив:


$config = require 'config.php';
$mysqli = new mysqli($config['host'], $config['username'], $config['password'], $config['dbname']);
  

Config php host (php: настройка host в конфигурационном файле)

Ошибка: "Connection refused" или "No such file or directory"

Причина: неверный host или порт. Для сокета MySQL укажите 'localhost' или полный путь к сокету. Для TCP-соединения используйте '127.0.0.1' и порт 3306. Решение: проверить настройки сервера MySQL и параметры в config.

Как использовать устаревшее расширение mysql_* (для справки)?

Функции mysql_connect(), mysql_select_db() и другие удалены из PHP 7.0. Их нельзя применять в новых проектах, но в старых кодовых базах они ещё встречаются.

Цель: миграция legacy-кода на современные драйверы.


$link = mysql_connect('localhost', 'user', 'pass');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb', $link);
$result = mysql_query('SELECT * FROM users', $link);
while ($row = mysql_fetch_assoc($result)) {
    echo $row['name'] . "<br>";
}
  

Config ini php (php: настройка php.ini)

Ошибка: "Call to undefined function mysql_connect()"

Решение: обновить код на PDO или MySQLi. Другого пути нет - расширение более не поддерживается.

Как хранить параметры подключения в .env файле?

Использование библиотеки vlucas/phpdotenv позволяет изолировать конфиденциальные данные от кода. Файл .env не попадает в репозиторий.

Цель: повышение безопасности, удобство деплоя на разных окружениях.


# .env
DB_HOST=localhost
DB_NAME=app
DB_USER=root
DB_PASS=secret
DB_DRIVER=mysql
  

Php config connect (php: настройка подключения к базе данных в config)


<?php
require 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$dsn = $_ENV['DB_DRIVER'] . ':host=' . $_ENV['DB_HOST'] . ';dbname=' . $_ENV['DB_NAME'];
$pdo = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASS']);
  

Define config php (php: определение констант через define в конфигурации)

Ошибка: "The environment file is not valid"

Причина: нарушен синтаксис .env (пробелы вокруг знака =, кавычки). Решение: проверить формат, каждая строка КЛЮЧ=значение без лишних пробелов.

Как настроить подключение через переменные окружения сервера?

Переменные окружения устанавливаются на уровне ОС или веб-сервера (например, в Apache SetEnv). PHP получает их через getenv() или суперглобальный массив $_SERVER.

Цель: нулевая конфигурация в коде, параметры задаются окружением.


<?php
$host = getenv('DB_HOST') ?: 'localhost';
$db = getenv('DB_NAME') ?: 'default';
$user = getenv('DB_USER') ?: 'root';
$pass = getenv('DB_PASS') ?: '';
$pdo = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
  

Проблема: переменные не определены, возвращают false

Проверьте, что переменные установлены в конфигурации сервера. Для CLI: export DB_HOST=.... Для Apache: директивы SetEnv в .htaccess или VirtualHost. Для Nginx: FastCGI параметры.

Как организовать единое подключение через паттерн Singleton?

Паттерн гарантирует, что в приложении существует только один экземпляр соединения. Реализация показана в основном решении (rbase). Вариант с ручной передачей конфига:


class DatabaseSingleton
{
    private static ?PDO $pdo = null;

    public static function connect(array $config): PDO
    {
        if (self::$pdo === null) {
            $dsn = "{$config['driver']}:host={$config['host']};dbname={$config['dbname']}";
            self::$pdo = new PDO($dsn, $config['user'], $config['pass'], $config['opts'] ?? []);
        }
        return self::$pdo;
    }
}
  

Цель: избежать множественных соединений, экономия ресурсов.

Проблема: тестирование становится сложным, так как состояние статическое

Решение: использовать внедрение зависимостей (DI-контейнер) вместо Singleton, чтобы соединение передавалось явно. Если же Singleton необходим, предусмотреть метод сброса для тестов: resetInstance().

Расширенные примеры настройки и использования подключения к БД

Пример 1: Конфигурационный файл с поддержкой окружений

Файл config.php может определять настройки в зависимости от среды (development/production).

Пример

<?php
$env = getenv('APP_ENV') ?: 'development';

$config = [
    'development' => [
        'host' => 'localhost',
        'dbname' => 'dev_db',
        'user' => 'dev',
        'pass' => 'dev',
        'options' => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_EMULATE_PREPARES => true,
        ],
    ],
    'production' => [
        'host' => 'db.example.com',
        'dbname' => 'prod_db',
        'user' => 'prod_user',
        'pass' => 'prod_pass',
        'options' => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
    ],
];

return $config[$env];

Результат: при вызове require 'config.php' возвращается массив, соответствующий окружению.

Пример 2: Класс Database с методами для транзакций и пагинации

Пример

<?php
class AdvancedDatabase
{
    private PDO $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function beginTransaction(): void
    {
        $this->pdo->beginTransaction();
    }

    public function commit(): void
    {
        $this->pdo->commit();
    }

    public function rollback(): void
    {
        $this->pdo->rollBack();
    }

    public function fetchPage(string $table, int $page, int $perPage): array
    {
        $offset = ($page - 1) * $perPage;
        $stmt = $this->pdo->prepare("SELECT * FROM $table LIMIT :limit OFFSET :offset");
        $stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll();
    }
}

$db = new AdvancedDatabase(Database::getInstance());
$users = $db->fetchPage('users', 1, 10);
print_r($users);

Результат: вывод массива из 10 записей таблицы users, начиная с первой страницы.

Пример 3: Обработка ошибок с логированием

Пример

<?php
function connectWithErrorHandling(): PDO
{
    try {
        $config = require 'config.php';
        $dsn = "{$config['driver']}:host={$config['host']};dbname={$config['dbname']}";
        $pdo = new PDO($dsn, $config['username'], $config['password'], $config['options']);
        return $pdo;
    } catch (PDOException $e) {
        // Логирование в файл
        error_log("Database connection failed: " . $e->getMessage(), 3, '/var/log/php_errors.log');
        // Пользователю показываем общее сообщение
        die('Извините, произошла ошибка базы данных. Пожалуйста, попробуйте позже.');
    }
}

try {
    $pdo = connectWithErrorHandling();
    $stmt = $pdo->query('SELECT 1');
    echo "Соединение установлено";
} catch (Exception $e) {
    echo "Не удалось выполнить запрос";
}

Результат: если соединение не удалось, в лог записывается детальная ошибка, а пользователь видит общее сообщение.

Пример 4: Использование разных драйверов PDO (SQLite, PostgreSQL)

Пример

<?php
$drivers = [
    'sqlite' => 'sqlite:/path/to/database.sqlite',
    'pgsql' => 'pgsql:host=localhost;dbname=mydb',
    'mysql' => 'mysql:host=localhost;dbname=mydb',
];

$driver = 'sqlite'; // можно менять
$pdo = new PDO($drivers[$driver], $driver === 'sqlite' ? null : 'user', $driver === 'sqlite' ? null : 'pass');
$stmt = $pdo->query('SELECT sqlite_version()');
$row = $stmt->fetch(PDO::FETCH_NUM);
echo "Версия SQLite: " . $row[0];

Результат: Версия SQLite: 3.31.1 (зависит от установленной версии).

Пример 5: Работа с пулом соединений через многократный вызов getInstance

Пример

<?php
$pdo1 = Database::getInstance();
$pdo2 = Database::getInstance();
var_dump($pdo1 === $pdo2); // bool(true)
// Доказательство единого подключения
$stmt = $pdo1->prepare('SELECT ? + ? AS sum');
$stmt->execute([10, 20]);
echo $stmt->fetchColumn(); // 30

Результат: на экран выводится bool(true) и 30.

PHP: настройка подключения к базе данных в config - comments

En
Php config connect (php)