我有一些带有 utf8mb4 字段的MySQL表,还有一些带有 utf8 的MySQL表。

在所有表的PDO连接字符串中使用utf8mb4是否安全?还是我必须将所有内容都转换为utf8mb4,或者启动两个不同的PDO连接?

编辑:问题不是“我可以将4字节字符存储到utf8列中吗?”我们已经知道不能,这不取决于连接,因此,如果一栏是utf8,则意味着它将不会接收4个字节的字符,例如国家或货币代码,电子邮件地址,用户名...,其中输入由应用程序验证。

最佳答案

使用以下脚本可以很容易地对此进行测试:

<?php

$pdo = new PDO('mysql:host=localhost;dbname=test', 'test', '');

$pdo->exec("
    drop table if exists utf8_test;
    create table utf8_test(
        conn varchar(50) collate ascii_bin,
        column_latin1  varchar(50) collate latin1_general_ci,
        column_utf8    varchar(50) collate utf8_unicode_ci,
        column_utf8mb4 varchar(50) collate utf8mb4_unicode_ci
    );
");

$latin = 'abc äŒé';
$utf8  = '♔♕';
$mb4   = '🛃 🔣';

$pdo->exec("set names utf8");

$pdo->exec("
    insert into utf8_test(conn, column_latin1, column_utf8, column_utf8mb4)
     values ('utf8', '$latin', '$latin $utf8', '$latin $utf8 $mb4')
");

$pdo->exec("set names utf8mb4");

$pdo->exec("
    insert into utf8_test(conn, column_latin1, column_utf8, column_utf8mb4)
     values ('utf8mb4', '$latin', '$latin $utf8', '$latin $utf8 $mb4')
");

$result = $pdo->query('select * from utf8_test')->fetchAll(PDO::FETCH_ASSOC);

var_export($result);

结果如下:
array (
  0 =>
  array (
    'conn' => 'utf8',
    'column_latin1' => 'abc äŒé',
    'column_utf8' => 'abc äŒé ♔♕',
    'column_utf8mb4' => 'abc äŒé ♔♕ ???? ????',
  ),
  1 =>
  array (
    'conn' => 'utf8mb4',
    'column_latin1' => 'abc äŒé',
    'column_utf8' => 'abc äŒé ♔♕',
    'column_utf8mb4' => 'abc äŒé ♔♕ 🛃 🔣',
  ),
)

如您所见,当我们处理utf8列时,不能将utf8mb4用作连接字符集(请参阅????)。但是,当使用utf8mb4列时,我们可以使用utf8进行连接。同样,写入和读取latinascii列也不会有问题。

原因是您可以用utf8编码任何latinasciiutf8mb4字符,但不能反之。因此,在这种情况下,使用utf8mb4作为连接的字符集是安全的。

关于php - 我可以安全地将utf8mb4连接与utf8列一起使用吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34595463/

10-11 11:03