実際に何が起きているのか
MySQLは動いている。PHPもインストール済み。接続文字列も問題なさそう。なのにスクリプトを実行すると、こんなエラーが出る:
Warning: mysqli_connect(): (HY000/2002): No such file or directory
PHPが見つけられない「ファイルやディレクトリ」とは、PHPスクリプトでも設定ファイルでもない。それはUnixソケットファイル――localhostで接続するときにMySQLが使う通信チャネルのことだ。
よくある落とし穴として、mysqli_connect()にlocalhostを渡してもTCP/IPは使われない。PHPはネットワークスタックを完全にスキップし、ファイルシステム上のUnixドメインソケットを探しに行く。PHPが/tmp/mysql.sockにソケットがあると思っているのに、MySQLが/var/run/mysqld/mysqld.sockに置いていたら、毎回このエラーが発生する。
デバッグ:ソケットの実際の場所を探す
まずMySQLが動いているか確認しよう:
sudo systemctl status mysql
# MariaDBの場合:
sudo systemctl status mariadb
動いていない? 起動すれば解決だ。それでも動いている? ソケットパスの不一致が原因だ。実際のソケットの場所を探そう:
mysql -u root -p -e "SHOW VARIABLES LIKE 'socket';"
出力例:
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| socket | /var/run/mysqld/mysqld.sock |
+---------------+--------------------------+
次に、PHPがソケットパスをどこだと思っているか確認する:
php -r "echo ini_get('mysqli.default_socket');"
あるいはphp.iniを直接検索する:
grep -r "mysqli.default_socket" /etc/php/
パスが違う? それが原因だ。パスは同じなのにソケットファイルがディスク上に存在しない? MySQLが動いていないか、起動時にクラッシュしている。
解決策1:localhostの代わりに127.0.0.1を使う(最速の修正)
localhostを127.0.0.1に変えるだけ。設定変更もサービス再起動も不要――たった一文字の違いで、PHPの接続方法がまったく変わる:
<?php
// 修正前(Unixソケットを使用 — ソケットパスが間違っていると失敗)
$conn = mysqli_connect('localhost', 'myuser', 'mypass', 'mydb');
// 修正後(TCP/IPを強制 — ソケットの問題を完全に回避)
$conn = mysqli_connect('127.0.0.1', 'myuser', 'mypass', 'mydb');
?>
127.0.0.1を使うと、PHPはポート3306でTCP接続する。MySQLはデフォルトでそこをリッスンしているので、ほとんどの環境ですぐに動作する。
PDOを使っている場合も同じ変更でOK:
<?php
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=mydb', 'myuser', 'mypass');
?>
解決策2:php.iniでソケットパスを修正する(正式な修正)
接続コードを変更できない場合――レガシーアプリや自分で管理していないCMSなど――PHPのソケット設定をMySQLが実際に使っている場所に合わせよう。
まず、有効なphp.iniの場所を確認する:
php --ini | grep "Loaded Configuration"
そのファイルを開き、SHOW VARIABLES LIKE 'socket'で確認したパスに合わせて3つのソケット設定をすべて更新する:
; php.ini内
mysqli.default_socket = /var/run/mysqld/mysqld.sock
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
mysql.default_socket = /var/run/mysqld/mysqld.sock
その後、PHPプロセスを再起動する:
# PHP-FPMの場合:
sudo systemctl restart php8.1-fpm
# Apache + mod_phpの場合:
sudo systemctl restart apache2
解決策3:コード内でソケットを明示的に指定する
php.iniのデフォルト値に頼るのではなく、mysqli_connect()にソケットパスを直接ハードコードする。ある接続はソケット、別の接続はTCPを使いたい場合に便利だ:
<?php
$conn = mysqli_connect(
'localhost',
'myuser',
'mypass',
'mydb',
3306,
'/var/run/mysqld/mysqld.sock' // ソケットパスを明示
);
?>
オブジェクト指向スタイルの場合:
<?php
$mysqli = new mysqli();
$mysqli->real_connect(
'localhost',
'myuser',
'mypass',
'mydb',
3306,
'/var/run/mysqld/mysqld.sock'
);
?>
システム別の主なソケットパス
ソケットの場所はディストリビューションやMySQLのバリアントによって異なる。確認すべき場所はここだ:
- Ubuntu/Debian (MySQL):
/var/run/mysqld/mysqld.sock - CentOS/RHEL (MySQL):
/var/lib/mysql/mysql.sock - MariaDB(多くのディストリビューション):
/var/run/mysqld/mysqld.sockまたは/tmp/mysql.sock - MAMP/XAMPP (macOS):
/Applications/MAMP/tmp/mysql/mysql.sock - Homebrew MySQL (macOS):
/tmp/mysql.sock
迷ったらSHOW VARIABLES LIKE 'socket'を実行しよう――MySQLは必ずファイルの場所を知っている。
修正の確認
アプリを触る前に、コマンドラインでテストしよう:
php -r "
\$conn = mysqli_connect('127.0.0.1', 'myuser', 'mypass', 'mydb');
if (\$conn) {
echo 'Connected successfully\n';
mysqli_close(\$conn);
} else {
echo 'Error: ' . mysqli_connect_error() . '\n';
}
"
あるいは、接続成功時にサーバーバージョンを表示するこの一時的なブロックをアプリに追加して確認する:
<?php
$conn = mysqli_connect('127.0.0.1', 'myuser', 'mypass', 'mydb');
if (!$conn) {
die('Connection failed: ' . mysqli_connect_error());
}
echo 'Connected. MySQL server version: ' . mysqli_get_server_info($conn);
mysqli_close($conn);
?>
まとめ
- PHPのデータベース接続において、
localhostと127.0.0.1は互換性がない。一方はUnixソケットファイルを使い、もう一方はTCP/IPで接続する。 - 「No such file or directory」はネットワークエラーではなく、ファイルシステムのエラーだ。PHPが想定するパスにソケットファイルが文字通り存在しないということだ。
- MySQLとMariaDBを切り替えたり、ディストリビューションを移行したりすると、ソケットパスが変わることがある。必ず再確認しよう。
- Dockerコンテナや、ソケットパスが変わりやすい混在環境では、
127.0.0.1のほうが移植性が高い――ディスク上のファイルの存在に依存しないからだ。

