Phpmyadmin 字符集致命错误 'Undefined index: utf8mb3'

Phpmyadmin Charsets fatal error 'Undefined index: utf8mb3'

我安装了一个新的 PHPMyAdmin 实例来使用 MySQL8。访问主页时,我收到一条警告消息:

Notice in ./libraries/classes/Charsets.php#154
 Undefined index: utf8mb3

Backtrace

./libraries/classes/Controllers/HomeController.php#163: PhpMyAdmin\Charsets::getServerCharset(,
boolean false,)
./libraries/classes/Routing.php#186: PhpMyAdmin\Controllers\HomeController->index(array)
./index.php#18: PhpMyAdmin\Routing::callControllerForRoute(
string '/',,,)

我的MySQL服务器和客户端编码是:utf8。 知道我该如何解决吗?

原因

这似乎是由 MySQL 8 在 MySQL ([mysqld]) 配置中将 character_set_server 设置为 utf8 时的错误引起的。

MySQL manual 状态:

MySQL immediately converts instances of utf8mb3 in statements to utf8, so in statements such as SHOW CREATE TABLE or SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNS or SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS, users see the name utf8 or utf8_collation_substring.

然而,查询SHOW VARIABLES LIKE 'character_set_server';仍然returns

----------------------+----------+
| Variable_name        | Value   |
+----------------------+---------+
| character_set_server | utf8mb3 |
+----------------------+---------+

-> utf8mb3

phpMyAdmin中的相关部分代码可以在libraries/classes/Charsets.php:

中找到
  /**
  * Get current server charset
  *
  * @param DatabaseInterface $dbi       DatabaseInterface instance
  * @param bool              $disableIs Disable use of INFORMATION_SCHEMA
  */
public static function getServerCharset(DatabaseInterface $dbi, bool $disableIs): Charset
{
    if (self::$serverCharset !== null) {
        return self::$serverCharset;
    }
    self::loadCharsets($dbi, $disableIs);
    $serverCharset = $dbi->getVariable('character_set_server');
    if (! is_string($serverCharset)) {// MySQL 5.7.8 fallback, issue #15614
        $serverCharset = $dbi->fetchValue('SELECT @@character_set_server;');
    }
    self::$serverCharset = self::$charsets[$serverCharset];
    return self::$serverCharset;
}

phpMyAdmin 在 libraries/classes/Charsets.php 中的方法 getServerCharset 中执行的操作(导致错误)如下:

  • 检查是否已经确定字符集。如果没有,

  • 它使用方法 loadCharsets 从 MySQL 服务器加载可用的字符集数组。然而,这是通过查询 SHOW CHARACTER SET; 或查询 information_schema 完成的。在这两种情况下,utf8(而不是 utf8mb3)都是 returned,如上文 MySQL 手册中所述。

  • 然后,它通过查询 SHOW VARIABLES LIKE 'character_set_server'; 获取服务器字符集(这里,utf8mb3 被 returned 作为结果,如上所示)。

  • 由于 MySQL 5.7.8 中的错误,我们可以忽略它。

  • 它把结果写入变量self::$serverCharset,方法是从所有的数组中获取键为$serverCharset(也就是utf8mb3)的数组元素服务器字符集可用。正如我们所知,可用服务器字符集数组中没有关键字 utf8mb3(只有 utf8,它是 utf8mb3 的别名)。因此,出现错误。

如何修复

要解决此问题,在查询 SHOW VARIABLES LIKE 'character_set_server'; 上 MySQL 应该改为 return utf8,这不是我们可以轻易影响的(错误报告可能必须创建),或者我们必须在 phpMyAdmin 源代码中解决它。

为此,我添加了

if ($serverCharset === "utf8mb3") {
    $serverCharset = "utf8";
}

行前

self::$serverCharset = self::$charsets[$serverCharset];

现在看起来像这样:

  /**
  * Get current server charset
  *
  * @param DatabaseInterface $dbi       DatabaseInterface instance
  * @param bool              $disableIs Disable use of INFORMATION_SCHEMA
  */
public static function getServerCharset(DatabaseInterface $dbi, bool $disableIs): Charset
{
    if (self::$serverCharset !== null) {
        return self::$serverCharset;
    }
    self::loadCharsets($dbi, $disableIs);
    $serverCharset = $dbi->getVariable('character_set_server');
    if (! is_string($serverCharset)) {// MySQL 5.7.8 fallback, issue #15614
        $serverCharset = $dbi->fetchValue('SELECT @@character_set_server;');
    }

    if ($serverCharset === "utf8mb3") {
        $serverCharset = "utf8";
    }

    self::$serverCharset = self::$charsets[$serverCharset];
    return self::$serverCharset;
}

该错误不应再发生。

我们正在寻找您,请在以后将此问题报告给我们的 GitHub 跟踪器

参见:issue #16931

这是官方修复:a2855079abccc05940286424d3017bf8ca9b3c7d

解决方案:安装 phpMyAdmin 5.1.1 或更新版本