PHP PDO: karakter seti, set adları?


189

Daha önce benim normal mysql_ * bağlantım vardı:

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

PDO için buna ihtiyacım var mı? Nereden almalıyım?

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

10
SQL kümesi nedeniyle "SET NAMES utf8" kaçınılmalıdır. Ayrıntılar için php.net/manual/tr/mysqlinfo.concepts.charset.php adresine bakın.
masakielastic

karakter sorunları yaşıyorsanız utf8 olarak ayarlamaktan başka seçeneğiniz olmayabilir. Ben take away aşağıdaki Cobra_Fast tarafından gösterildiği gibi bağlantı dizesini kullanmak gerektiğini düşünüyorum . SQL deyimlerinizi ilişkili parametrelerle hazırlamak için PDO :: Hazırlık kullanın.
user12345

1
@masakielastic, harmanlamayı "SET NAMES utf8 COLLATE utf8_unicode_ci" olarak nasıl belirtmeliyiz
datasn.io

Yanıtlar:


460

Bağlantı dizenizde şöyle olacak:

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

Ancak PHP 5.3.6'dan önce karakter seti seçeneği yoksayıldı. PHP'nin daha eski bir sürümünü kullanıyorsanız, bunu şu şekilde yapmanız gerekir:

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

15
Bu davranışın 5.3.6'da değiştiğini ve şimdi doğru çalıştığını belirtmek gerekir.
igorw

15
shoudle UTF-8 "mysql yerine instaff olmak: host = $ host; dbname = $ db; charset = utf8"
od3n

3
PHP'nin güncel bir sürümünü kullanıyorsanız aşağıdaki cevapları dikkate almayın: php 5.3.8'de gayet iyi çalışıyor.
kasimir

4
Bu durumda da harmanlamayı belirtmem gerekiyor mu? 'SET NAMES utf8 COLLATE utf8_unicode_ci' gibi?
datasn.io

2
Teşekkürler! Günümü kurtardım!
Aleksandr

64

PHP 5.3.6'dan önce karakter kümesi yoksayıldı. PHP'nin daha eski bir sürümünü kullanıyorsanız, bunu şu şekilde yapmanız gerekir:

<?php

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

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

?>

1
Modlara not: Bu doğru cevaptır ve kabul edilen cevapta bu bilginin düzenlenmesi için bir yıl önce yayınlanmıştır.
dotancohen

42

Muhtemelen bunu yapmanın en zarif yolu.
PDO yapıcı çağrısında, ancak buggy charset seçeneğinden kaçınmak (yukarıda belirtildiği gibi):

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

Benim için harika çalışıyor.


1
Anladığım kadarıyla bu php 5.3.0 için buggy olduğunu. Bu durumda sayısını ziyade böyle adını başvurarak dizideki seçeneği girmeniz gerekir: array(1002 => 'SET NAMES utf8',...).
JDelage

İpucu için teşekkürler! Yukarıdaki kodu PHP'nin farklı 5.3.X sürümlerini çalıştıran birden çok üretim sisteminde başarıyla kullanıyorum, ancak aslında bunların hiçbiri 5.3.0 değil.
Jpsy

4
Bence veritabanına özel seçenekler olmadan daha zarif olabilir
Aalex Gabi

Doğru, MYSQL_ATTR_INIT_COMMAND yalnızca MySQL veritabanları için kullanılabilir (her db türü için kullanılabilir komutlar için php.net/manual/de/pdo.drivers.php alt sayfalarına bakın ). Ama OP tam da bunu istedi.
Jpsy

charset=utf8dsn dizesinde geçen çalışır! Sorunu groups.google.com/d/msg/auraphp/syMS26Rz-q8/9laQr9tR4EoJ adresinde
Hari KT

16

Tamlık için, PDO'dan MySQL'e bağlanırken kodlamayı ayarlamanın üç yolu vardır ve hangilerinin kullanılabilir olduğu PHP sürümünüze bağlıdır. Tercih sırası:

  1. charset parametresini DSN dizesinde
  2. Bağlantı seçeneği SET NAMES utf8ile çalıştırPDO::MYSQL_ATTR_INIT_COMMAND
  3. SET NAMES utf8Manuel olarak çalıştır

Bu örnek kod üçünü de uygular:

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

Üçünü de yapmak muhtemelen aşırıdır (dağıtmayı veya yeniden kullanmayı planladığınız bir sınıf yazmıyorsanız).


1
ODBC / Access eşdeğeri var mı? Şimdi çalışan bir Oracle ve MySQL PHP PDO UTF8 bağlantısı var ama ODBC / Access için çalışamıyor.
Ocak

2
Oh ve asla veritabanı şifrenizi TANIMLAMAYIN. Süper küreseller kadar küreseller ve parolalarla çalışırken iyi bir şey değil.
Xesau

2

Ben sadece veritabanınızın COLLATE utf8_general_ci ile oluşturulduğundan emin olmak istediğinizi veya kullanmak istediğiniz herhangi bir harmanlamayı eklemek istediğinizi eklemek istersiniz, Else amaçlanandan başka bir tane ile sonuçlanabilir.

Phpmyadmin'de veritabanınızı tıklatıp işlemleri seçerek harmanlamayı görebilirsiniz. Veritabanınızdan başka bir harmanlama içeren tablolar oluşturmayı denerseniz, tablolarınız yine de veritabanı harmanlamasıyla sonuçlanır.

Bu yüzden tablo oluşturmadan önce veritabanınızın harmanlamasının doğru olduğundan emin olun. Umarım bu birini birkaç saat kurtarır


1
"Eğer veritabanından başka bir harmanlama ile tablolar oluşturmaya çalışırsanız, tablolarınız zaten veritabanı harmanlama ile sona erecek" - Doğru olduğunu düşünmüyorum. Tablo harmanlaması, veritabanının harmanlamasından önceliklidir. dev.mysql.com/doc/refman/5.5/en/charset-table.html
humble_wolf

2

DSN charset seçeneği aslında yok sayılır çünkü ek bir sorguya ihtiyacım olduğunu düşünüyorum. diğer cevabın yorumunda yayınlanan bağlantıya bakınız.

Drupal 7'nin http://api.drupal.org/api/drupal/includes--database--mysql--database.inc/function/DatabaseConnection_mysql%3A%3A__construct/7 içinde bunu nasıl yaptığına bakmak :

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

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

1
Bu cevap muhtemelen doğru ve yararlı olsa da, sorunun çözülmesine nasıl yardımcı olduğunu açıklamak için bununla birlikte bir açıklama eklemeniz tercih edilir. Bu, özellikle çalışmayı durdurmasına neden olan bir değişiklik varsa (muhtemelen ilgisiz) ve kullanıcıların bir zamanlar nasıl çalıştığını anlamaları gerekiyorsa, özellikle yararlı olur.
Erty Seidohl

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

0

Bu kodu test ediyorum ve

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

Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
rollstuhlfahrer

-1

$ con = yeni PDO ("mysql: host = $ dbhost; dbname = $ veritabanı; karakter kümesi = $ kodlama ", "$ dbuser", "$ dbpassword");

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.