相关文章推荐
直爽的荔枝  ·  Git | ...·  5 月前    · 
打篮球的蛋挞  ·  【Unity Shader】 ...·  1 年前    · 
礼貌的啄木鸟  ·  java - ...·  2 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams "SET NAMES utf8" should be avoided because of SQL injection. See php.net/manual/en/mysqlinfo.concepts.charset.php for he details. masakielastic Jun 8, 2013 at 9:47 if you have charset issues then you may have no choice but to set to utf8. I think the take away should be use the connection string as shown by Cobra_Fast below. Use PDO::prepare to prepare your SQL statements with bound parameters. user12345 Jul 2, 2014 at 23:16 @masakielastic, then how should we specify collation as "SET NAMES utf8 COLLATE utf8_unicode_ci" datasn.io Sep 12, 2014 at 11:17

You'll have it in your connection string like:

"mysql:host=$host;dbname=$db;charset=utf8mb4"

HOWEVER, prior to PHP 5.3.6, the charset option was ignored. If you're running an older version of PHP, you must do it like this:

$dbh = new PDO("mysql:host=$host;dbname=$db",  $user, $password);
$dbh->exec("set names utf8mb4");
                Ignore the answers below if you are using an up-to-date version of PHP: it works just fine in php 5.3.8.
– kasimir
                May 2, 2012 at 15:02
                Do I have to also specify collation in this case? Such as 'SET NAMES utf8 COLLATE utf8_unicode_ci'?
– datasn.io
                Sep 12, 2014 at 11:15

Prior to PHP 5.3.6, the charset option was ignored. If you're running an older version of PHP, you must do it like this:

$dbh = new PDO("mysql:$connstr", $user, $password); $dbh -> exec("set names utf8"); Note to mods: This is the correct answer, and it was posted one year before the accepted answer had this information edited into it. – dotancohen Dec 24, 2013 at 6:38

This is probably the most elegant way to do it.
Right in the PDO constructor call, but avoiding the buggy charset option (as mentioned above):

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

Works great for me.

My understanding is that this also is buggy for php 5.3.0. In that case you need to enter the option in the array by referencing its number rather than its name like this: array(1002 => 'SET NAMES utf8',...). – JDelage Feb 24, 2012 at 23:50 Thanks for the hint! I am using the above code successfully on multiple production systems running different 5.3.X versions of PHP, but actually none of them is 5.3.0. – Jpsy Feb 26, 2012 at 16:08 True, the MYSQL_ATTR_INIT_COMMAND is only available for MySQL databases (for available commands for each db type see the sub-pages of php.net/manual/de/pdo.drivers.php). But this is exactly what the OP has asked for. – Jpsy Nov 6, 2012 at 11:54 passing charset=utf8 in the dsn string works! I was trying to figure out the issue at groups.google.com/d/msg/auraphp/syMS26Rz-q8/9laQr9tR4EoJ – Hari K T Nov 14, 2013 at 5:17

For completeness, there're actually three ways to set the encoding when connecting to MySQL from PDO and which ones are available depend on your PHP version. The order of preference would be:

  • charset parameter in the DSN string
  • Run SET NAMES utf8 with PDO::MYSQL_ATTR_INIT_COMMAND connection option
  • Run SET NAMES utf8 manually
  • This sample code implements all three:

    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);

    Doing all three is probably overkill (unless you're writing a class you plan to distribute or reuse).

    Is there an ODBC/Access equivalent? I now have a working Oracle and MySQL PHP PDO UTF8 connection but I can't get it working for ODBC/Access. – Jan May 28, 2015 at 13:32 Oh and never DEFINE your database password. They're as global as superglobals, and that's not a good thing when you're you're working with passwords. – Xesau Aug 24, 2015 at 19:56 I'm on PHP 7.4 and still had to run a separate query, in order to get non-latin characters displayed when getting the data SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci. The utf8mb4 in dsn wasn't enough – Moseleyi Jul 26, 2021 at 20:34 While this answer is probably correct and useful, it is preferred if you include some explanation along with it to explain how it helps to solve the problem. This becomes especially useful in the future, if there is a change (possibly unrelated) that causes it to stop working and users need to understand how it once worked. – Erty Seidohl May 23, 2018 at 22:03 $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 );

    I think you need an additionally query because the charset option in the DSN is actually ignored. see link posted in the comment of the other answer.

    Looking at how Drupal 7 is doing it in http://api.drupal.org/api/drupal/includes--database--mysql--database.inc/function/DatabaseConnection_mysql%3A%3A__construct/7:

    // Force MySQL to use the UTF-8 character set. Also set the collation, if a
    // certain one has been set; otherwise, MySQL defaults to 'utf8_general_ci'
    // for UTF-8.
    if (!empty($connection_options['collation'])) {
      $this->exec('SET NAMES utf8 COLLATE ' . $connection_options['collation']);
    else {
      $this->exec('SET NAMES utf8');
    

    I just want to add that you have to make sure your database is created with COLLATE utf8_general_ci or whichever collation you want to use, Else you might end up with another one than intended.

    In phpmyadmin you can see the collation by clicking your database and choose operations. If you try create tables with another collation than your database, your tables will end up with the database collation anyways.

    So make sure the collation for your database is right before creating tables. Hope this saves someone a few hours lol

    "If you try create tables with another collation than your database, your tables will end up with the database collation anyways" - I don't think it is correct. Table collation takes precedence over database's collation. dev.mysql.com/doc/refman/5.5/en/charset-table.html – humble_wolf Oct 7, 2017 at 9:32
    $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'];
                    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
    – rollstuhlfahrer
                    Apr 6, 2018 at 7:07
    

    How it will look:

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

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.