Ошибка PDOException SQLSTATE[HY000] [2002] No such file or directory в Laravel
Всем привет! Я новичок в PHP и Laravel, и у меня возникла проблема при попытке подключиться к базе данных MySQL. Когда я запускаю миграцию через php artisan migrate, появляется следующая ошибка:
PDOException: SQLSTATE[HY000] [2002] No such file or directory
Я использую Laravel 10 на macOS. Вот мой файл .env:
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=my_database
DB_USERNAME=root
DB_PASSWORD=secret
MySQL установлен через Homebrew, и сервер запущен — я проверил это через brew services list. Также я могу подключиться к базе через терминал командой mysql -u root -p. Но Laravel почему-то не видит соединение. Что я делаю не так? Пробовал менять DB_HOST на 127.0.0.1, но тогда ошибка меняется на Connection refused. Помогите разобраться, пожалуйста!
Причина ошибки и её решение
Ошибка SQLSTATE[HY000] [2002] No such file or directory возникает из-за того, что PHP пытается подключиться к MySQL через Unix-сокет, а не через TCP/IP. В macOS и Linux MySQL по умолчанию может слушать Unix-сокет, расположенный в файловой системе (обычно /tmp/mysql.sock или /var/mysql/mysql.sock). Когда вы указываете DB_HOST=localhost, PHP-драйвер PDO интерпретирует это как попытку подключения через сокет, а не через TCP. Если сокет отсутствует или путь к нему неверный, возникает данная ошибка.
Проверка расположения сокета MySQL
Сначала узнайте, где находится Unix-сокет MySQL. Выполните в терминале:
mysql -u root -p -e "SHOW VARIABLES LIKE 'socket';"
Вы увидите что-то вроде:
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| socket | /tmp/mysql.sock |
+---------------+-----------------+
Способ 1: Использовать TCP/IP подключение (рекомендуется)
Самый простой способ — заставить PHP подключаться через TCP/IP, указав DB_HOST=127.0.0.1 вместо localhost. Однако, если вы уже пробовали это и получили Connection refused, значит MySQL не слушает TCP-порт. Чтобы исправить обе проблемы, сделайте следующее:
- Откройте конфигурационный файл MySQL (обычно
/etc/my.cnfили/usr/local/etc/my.cnfдля Homebrew). - Найдите секцию
[mysqld]и добавьте или раскомментируйте строку:
[mysqld]
bind-address = 127.0.0.1
port = 3306
- Перезапустите MySQL:
brew services restart mysql
- Теперь измените
.env:
DB_HOST=127.0.0.1
DB_PORT=3306
После этого ошибка должна исчезнуть.
Способ 2: Указать путь к сокету (альтернатива)
Если вы предпочитаете использовать Unix-сокет, добавьте в .env параметр DB_SOCKET:
DB_CONNECTION=mysql
DB_HOST=localhost
DB_SOCKET=/tmp/mysql.sock
DB_DATABASE=my_database
DB_USERNAME=root
DB_PASSWORD=secret
Убедитесь, что путь к сокету совпадает с тем, который вы получили из запроса SHOW VARIABLES LIKE 'socket';.
Способ 3: Настройка через config/database.php
Вы также можете явно настроить подключение в файле config/database.php:
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', '/tmp/mysql.sock'),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
],
После любых изменений не забудьте очистить кэш конфигурации:
php artisan config:clear
Важные моменты
- Всегда используйте
127.0.0.1вместоlocalhostв продакшене, если не уверены в настройках сокета. - После изменения
.envперезапустите сервер разработки Laravel (php artisan serve). - Проверьте, что MySQL действительно запущен:
brew services listилиsystemctl status mysql.
Дополнительное решение: Использование Docker или Homestead
Если вы часто сталкиваетесь с проблемами подключения к MySQL на локальной машине, рассмотрите использование Docker-контейнера для MySQL. Это изолирует среду и устраняет проблемы с путями сокетов. Пример docker-compose.yml:
version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: my_database
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
Затем в .env укажите:
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_database
DB_USERNAME=root
DB_PASSWORD=secret
Docker всегда использует TCP/IP, поэтому ошибки с сокетом не возникнут. Если вы используете Laravel Homestead (Vagrant), проблема часто решается указанием DB_HOST=192.168.10.10 или DB_HOST=127.0.0.1 с портом 33060 (стандартный проброс портов в Homestead).
Быстрая диагностика
Чтобы проверить, какой именно способ подключения использует PHP, выполните скрипт:
<?php
try {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'secret');
echo "Connected via socket";
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
Если ошибка — значит проблема в сокете. Замените localhost на 127.0.0.1 и повторите — если работает, то решение очевидно.
Ответов пока нет.
Войдите чтобы оставить ответ