PHP PDO: charset, set names?

PhpMysqlPdo

Php Problem Overview


I had this previously in my normal mysql_* connection:

mysql_set_charset("utf8",$link);
mysql_query("SET NAMES 'UTF8'");

Do I need it for the PDO? And where should I have it?

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

Php Solutions


Solution 1 - Php

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

Solution 2 - Php

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:

<?php

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

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

?>

Solution 3 - Php

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.

Solution 4 - Php

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:

  1. charset parameter in the DSN string
  2. Run SET NAMES utf8 with PDO::MYSQL_ATTR_INIT_COMMAND connection option
  3. Run SET NAMES utf8 manually

This sample code implements all three:

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

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

Solution 5 - Php

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

Solution 6 - Php

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

Solution 7 - Php

$conn = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass);

Solution 8 - Php

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

Solution 9 - Php

I test this code and

$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'];
}

Solution 10 - Php

in my case, i had to add this line:

$conn->exec("set names utf8"); //Support utf8

How it will look:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKaremView Question on Stackoverflow
Solution 1 - PhpCobra_FastView Answer on Stackoverflow
Solution 2 - Php9nix00View Answer on Stackoverflow
Solution 3 - PhpJpsyView Answer on Stackoverflow
Solution 4 - PhpÁlvaro GonzálezView Answer on Stackoverflow
Solution 5 - PhpBerdirView Answer on Stackoverflow
Solution 6 - PhpJayanit SataniView Answer on Stackoverflow
Solution 7 - PhpGauravbhai DaxiniView Answer on Stackoverflow
Solution 8 - PhpMedda86View Answer on Stackoverflow
Solution 9 - Phpelite andotView Answer on Stackoverflow
Solution 10 - PhpSuleiman 700View Answer on Stackoverflow