MeWrite Docs

Laravel PDO Invalid Attribute Exception (PHP 8.2)

PHP 8.2/8.1でLaravelのPDO接続時にinvalid attribute例外が発生する問題

概要

PHP 8.2.9/8.1.22以降でLaravelを使用すると、データベース接続時に「PDO invalid attribute」例外が発生する問題です。PHPのマイナーバージョンアップ後に突然発生することがあります。

エラーメッセージ

PDOException: SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args))
InvalidArgumentException: Invalid PDO attribute
PDOException: SQLSTATE[HY000]: General error: invalid attribute

原因

  1. PHP 8.2の仕様変更: PDO属性の検証が厳格化された
  2. MySQL/MariaDBドライバの非互換性: 古いドライバとPHP 8.2の組み合わせ問題
  3. 無効なPDO属性の設定: config/database.phpで非サポート属性を指定
  4. Laravel/Doctrineの非互換性: 古いバージョンとの互換性問題

解決策

1. database.phpの設定を確認・修正

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// config/database.php
'mysql' => [
    'driver' => 'mysql',
    'url' => env('DATABASE_URL'),
    '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', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'prefix_indexes' => true,
    'strict' => true,
    'engine' => null,
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        // 問題のある属性を削除または条件付きで設定
    ]) : [],
],

2. 無効な属性を削除

1
2
3
4
5
6
7
8
9
// 問題を引き起こす可能性のある属性
'options' => [
    // この属性がPHP 8.2で問題を起こすことがある
    // PDO::ATTR_EMULATE_PREPARES => false,

    // 代わりに以下のように設定
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
],

3. Laravelのアップデート

1
2
3
4
5
# Laravelフレームワークを最新に更新
composer update laravel/framework

# または特定バージョンに更新
composer require laravel/framework:^10.0

4. doctrine/dbalのアップデート

1
2
3
4
5
# doctrine/dbalが原因の場合
composer update doctrine/dbal

# または特定バージョンに固定
composer require doctrine/dbal:^3.6

5. PHPバージョンの確認と対応

1
2
3
4
5
6
7
8
# PHPバージョン確認
php -v

# PDO拡張の確認
php -m | grep pdo

# PDOドライバ情報
php -i | grep PDO

6. 条件付きPDO属性設定

1
2
3
4
5
6
7
8
// config/database.php
'options' => extension_loaded('pdo_mysql') ? array_filter([
    // PHP 8.2以降では一部属性をスキップ
    PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) + (version_compare(PHP_VERSION, '8.2.0', '<') ? [
    // PHP 8.2未満でのみ設定する属性
    PDO::ATTR_EMULATE_PREPARES => false,
] : []) : [],

7. 接続オプションのクリア

1
2
3
4
5
// 問題が解決しない場合、オプションを最小限に
'mysql' => [
    // ... 他の設定
    'options' => [],  // オプションをクリア
],

8. MySQLドライバの更新

1
2
3
4
5
6
7
8
9
# Ubuntu/Debian
sudo apt update
sudo apt install php8.2-mysql

# CentOS/RHEL
sudo yum update php-mysqlnd

# macOS (Homebrew)
brew upgrade php

9. SSL接続の設定見直し

1
2
3
4
5
// SSL接続が問題の場合
'options' => [
    PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,  // 開発環境のみ
],

10. カスタムPDO接続クラス

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// app/Database/MySqlConnection.php
namespace App\Database;

use Illuminate\Database\MySqlConnection as BaseMySqlConnection;

class MySqlConnection extends BaseMySqlConnection
{
    protected function getDefaultPostProcessor()
    {
        // カスタム処理
        return parent::getDefaultPostProcessor();
    }
}

// app/Providers/AppServiceProvider.php
use Illuminate\Database\Connection;
use App\Database\MySqlConnection;

public function register(): void
{
    Connection::resolverFor('mysql', function ($connection, $database, $prefix, $config) {
        return new MySqlConnection($connection, $database, $prefix, $config);
    });
}

デバッグ方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 接続テスト
Route::get('/db-test', function () {
    try {
        $pdo = DB::connection()->getPdo();
        dump('PDO Version: ' . $pdo->getAttribute(PDO::ATTR_CLIENT_VERSION));
        dump('Server Version: ' . $pdo->getAttribute(PDO::ATTR_SERVER_VERSION));
        return 'Connection successful';
    } catch (\Exception $e) {
        return 'Error: ' . $e->getMessage();
    }
});

よくある間違い

  • PHPアップデート後にLaravelをアップデートしない
  • 古い設定ファイルをそのまま使い続ける
  • 非サポートのPDO属性を設定に残す
  • SSL証明書の設定が古いまま

関連エラー

参考リンク

Laravel の他のエラー

最終更新: 2025-12-14