PHP PDO:字符集,集合名称?

PHP PDO:字符集,集合名称?,php,mysql,pdo,Php,Mysql,Pdo,我以前在正常的mysql_*连接中使用过: mysql_set_charset("utf8",$link); mysql_query("SET NAMES 'UTF8'"); PDO需要它吗?我应该把它放在哪里 $connect = new PDO("mysql:host=$host;dbname=$db", $user, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 您将在连接字符串中包含它,如: "mysql

我以前在正常的mysql_*连接中使用过:

mysql_set_charset("utf8",$link);
mysql_query("SET NAMES 'UTF8'");
PDO需要它吗?我应该把它放在哪里

$connect = new PDO("mysql:host=$host;dbname=$db", $user, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

您将在连接字符串中包含它,如:

"mysql:host=$host;dbname=$db;charset=utf8"
但是,在PHP5.3.6之前,字符集选项被忽略。如果您运行的是旧版本的PHP,则必须按照以下方式执行:

$dbh = new PDO("mysql:$connstr",  $user, $password);
$dbh->exec("set names utf8");
<?php

    $dbh = new PDO("mysql:$connstr",  $user, $password);

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

?>

我认为您需要另外一个查询,因为DSN中的字符集选项实际上被忽略了。参见另一个答案评论中的链接

看看Drupal 7是如何在中实现的:


在PHP5.3.6之前,字符集选项被忽略。如果您运行的是旧版本的PHP,则必须按照以下方式执行:

$dbh = new PDO("mysql:$connstr",  $user, $password);
$dbh->exec("set names utf8");
<?php

    $dbh = new PDO("mysql:$connstr",  $user, $password);

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

?>

这可能是最优雅的方式。
就在PDO构造函数调用中,但要避免错误的字符集选项(如上所述):


非常适合我。

为了完整起见,当从PDO连接到MySQL时,实际上有三种方法可以设置编码,哪些方法可用取决于您的PHP版本。优先顺序为:

  • DSN字符串中的
    charset
    参数
  • 使用
    PDO::MYSQL\u ATTR\u INIT\u命令运行
    SET NAMES utf8
  • 手动运行
    设置名称utf8
  • 此示例代码实现了以下三个方面:

    <?php
    
    define('DB_HOST', 'localhost');
    define('DB_SCHEMA', 'test');
    define('DB_USER', 'test');
    define('DB_PASSWORD', 'test');
    define('DB_ENCODING', 'utf8');
    
    
    $dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_SCHEMA;
    $options = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    );
    
    if( version_compare(PHP_VERSION, '5.3.6', '<') ){
        if( defined('PDO::MYSQL_ATTR_INIT_COMMAND') ){
            $options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . DB_ENCODING;
        }
    }else{
        $dsn .= ';charset=' . DB_ENCODING;
    }
    
    $conn = @new PDO($dsn, DB_USER, DB_PASSWORD, $options);
    
    if( version_compare(PHP_VERSION, '5.3.6', '<') && !defined('PDO::MYSQL_ATTR_INIT_COMMAND') ){
        $sql = 'SET NAMES ' . DB_ENCODING;
        $conn->exec($sql);
    }
    

    我只想补充一点,您必须确保您的数据库是使用COLLATUTF8\u general\u ci或您想要使用的任何排序规则创建的,否则您可能会得到另一个超出预期的排序规则


    在phpmyadmin中,您可以通过单击数据库并选择操作来查看排序规则。如果尝试使用数据库以外的其他排序规则创建表,则表最终将使用数据库排序规则

    因此,在创建表之前,请确保数据库的排序规则正确。希望这能节省一些时间lol

    我测试了这段代码并

    $con="";
    $MODE="";
    $dbhost = "localhost";
    $dbuser = "root";
    $dbpassword = "";
    $database = "name";
    
    $con = new PDO ( "mysql:host=$dbhost;dbname=$database", "$dbuser", "$dbpassword", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    $con->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );   
    
    $db=new PDO('mysql:host=localhost;dbname=cwDB','root','',
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    $sql="select * from products  ";
    $stmt=$db->prepare($sql);
    $stmt->execute();
    while($result=$stmt->fetch(PDO::FETCH_ASSOC)){                  
        $id=$result['id'];
    }
    

    在我的情况下,我必须添加这一行:

    $conn->exec("set names utf8"); //Support utf8
    
    它将是什么样子:

    $conn = new PDO("mysql:host=$servername;dbname=$db", $username, $password);
    $conn->exec("set names utf8"); //Support utf8
    


    值得注意的是,这种行为在5.3.6中发生了变化,现在工作正常。应该是UTF-8的utf8 instaead“mysql:host=$host;dbname=$db;charset=utf8”如果您使用的是最新版本的PHP,请忽略下面的答案:它在PHP5.3.8中工作正常。在这种情况下,我还需要指定排序规则吗?例如“SET NAMES utf8 COLLATE utf8\u unicode\u ci”?从utf8切换到utf8mb4。我的理解是,这对于PHP5.3.0来说也是一个错误。在这种情况下,您需要通过引用其编号而不是名称在数组中输入选项,如下所示:
    array(1002=>'SET NAMES utf8',…)
    。感谢您的提示!我在运行不同5.3.X版本PHP的多个生产系统上成功地使用了上述代码,但实际上没有一个是5.3.0。我认为如果没有特定于数据库的选项,它可能会更优雅。MYSQL\u ATTR\u INIT\u命令仅适用于MYSQL数据库(有关每种db类型的可用命令,请参阅的子页)。但这正是OP所要求的。在dsn字符串中传递
    charset=utf8
    是有效的!我试图在“SET NAMES utf8”中找出问题所在应避免使用,因为SQL注入。有关详细信息,请参阅。如果您有字符集问题,则您可能别无选择,只能设置为utf8。我认为应该使用以下命令。使用PDO::prepare使用绑定参数准备SQL语句。@Masakelastic,那么我们应该如何将排序规则指定为“集合名称utf8校对utf8\U unicode\U ci”"mods注意:这是正确的答案,在被接受的答案将此信息编辑到其中一年前发布。是否有ODBC/Access等效项?我现在有一个可以工作的Oracle和MySQL PHP PDO UTF8连接,但我无法让它在ODBC/Access中工作。哦,而且从未定义您的数据库密码。它们与超级全局一样全局s、 当您使用密码时,这不是一件好事。“如果您尝试使用数据库以外的其他排序规则创建表,那么您的表最终将使用数据库排序规则”-我认为这是不正确的。表排序优先于数据库排序。虽然此代码可能回答此问题,但提供有关此代码为什么和/或如何回答此问题的其他上下文可提高其长期价值。虽然此答案可能是正确和有用的,但最好包含一些解释这在将来特别有用,如果有变化(可能无关)导致它停止工作,并且用户需要了解它曾经是如何工作的。
    $conn = new PDO("mysql:host=$servername;dbname=$db", $username, $password);
    $conn->exec("set names utf8"); //Support utf8