STB
STB

Reputation: 35

Phpmyadmin Charsets fatal error 'Undefined index: utf8mb3'

I installed a new instance of PHPMyAdmin to work with MySQL8. When accessing the main page I receive an alert with the message:

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 '/',,,)

My MySQL server and client encoding is: utf8. Any idea how I can fix it?

Upvotes: 2

Views: 5652

Answers (2)

William Desportes
William Desportes

Reputation: 1711

We are looking for you, please in future report this issues to our GitHub tracker

See: issue #16931

Here is the official fix: a2855079abccc05940286424d3017bf8ca9b3c7d

Solution: install phpMyAdmin 5.1.1 or newer

Upvotes: 1

user40974
user40974

Reputation: 354

Cause

This seems to be caused by a bug in MySQL 8 when setting character_set_server to utf8 in the MySQL ([mysqld]) config.

The MySQL manual states:

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.

However, the query SHOW VARIABLES LIKE 'character_set_server'; still returns

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

-> utf8mb3

The relevant part of the code in phpMyAdmin can be found in 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;
}

What phpMyAdmin is doing in the method getServerCharset in libraries/classes/Charsets.php (which is causing the error) is the following:

  • It checks whether it has already determined the charset. If not,

  • it loads an array of charsets available from the MySQL server with the method loadCharsets. This however is done either by the query SHOW CHARACTER SET; or by querying information_schema. In both cases, utf8 (instead of utf8mb3) is returned, as explained above in the MySQL manual.

  • Then, it gets the server charset with the query SHOW VARIABLES LIKE 'character_set_server'; (Here, utf8mb3 is returned as the result, as seen above).

  • There is a fallback (not relevant in our case) due to a bug in MySQL 5.7.8, which we can ignore.

  • It writes the result into the variable self::$serverCharset, by getting the array element with the key $serverCharset (which is utf8mb3) from the array of all server charsets available . As we know, there is no key utf8mb3 in the array of the available server charsets (only utf8 which is the alias for utf8mb3). Therefore, the error occurs.

How to fix it

To fix this, either MySQL should instead return utf8 on the query SHOW VARIABLES LIKE 'character_set_server';, which isn't something we can easily influence (a bug report might have to be created), or we have to work around it in the phpMyAdmin source code.

To do this, I added

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

before the line

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

so that it now looks like this:

  /**
  * 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;
}

The error should not occur anymore.

Upvotes: 4

Related Questions