2010-08-12 37 views
7

Khi truy cập Cơ sở dữ liệu Microsoft SQL từ PHP bằng PDO_ODBC với mã sau, tôi gặp sự cố mã hóa. Khi xuất văn bản từ DB bị cắt xén.Vấn đề mã hóa ký tự với PDO_ODBC

$dsn = "odbc:DRIVER={SQL Server};SERVER=$hostname;DATABASE=$database;charset=UTF-8"; 
$pdo = new PDO($dsn,$username,$password); 
$sql = "SELECT text FROM atable"; 
$result = $PDO->query($sql); 
while($data = $result->fetchObject()){ 
    $values[] = $data->text; 
} 
dpm($values); 

garbled output http://image.bayimg.com/naomcaacd.jpg

này được thực hiện từ một module Drupal. Tất cả mọi thứ trong Drupal được thực hiện để làm việc với UTF-8. Giải pháp sạch nhất là có thể lấy dữ liệu từ cơ sở dữ liệu trong UTF-8 hoặc để chuyển đổi nó UTF-8 trước khi xuất.

tôi đã cố gắng những không có thành công

  • $dsn = "odbc:DRIVER={SQL Server};SERVER=$hostname;DATABASE=$database;client_charset=utf-8"
  • $dsn = "odbc:DRIVER={SQL Server};SERVER=$hostname;DATABASE=$database;charset=utf-8"
  • $pdo->exec('SET NAMES utf8') sau new PDO(...)
  • $pdo->exec('SET CHARACTER SET utf8'); sau new PDO(...)

PS: Mã hiện đang developped trên Windows nhưng nó có để làm việc trên GNU/Linux.

Trả lời

5

Khi chạy trên Linux và sử dụng trình điều khiển FreeTDS, bộ ký tự cho máy khách có thể được định cấu hình với cài đặt client charset trong tệp freetds.conf. Để tệp freetds.conf được sử dụng khi sử dụng ODO PDBC và unixODBC, một tệp cần phải định cấu hình nguồn dữ liệu ODBC bằng cách sử dụng ODBC-combined configuration. Khi ODBC-only configuration được sử dụng để định cấu hình nguồn dữ liệu ODBC, tệp freetds.conf không được sử dụng. Với điều này tôi đã có thể lấy và chèn dữ liệu UTF-8 từ/vào cơ sở dữ liệu MS SQL Server.

Là một anh chàng Linux/Unix, tôi không thể hiểu/tìm cách cấu hình bộ ký tự được sử dụng khi PDO ODBC được sử dụng trên Windows. Sự hiểu biết mơ hồ của tôi là khi được cấu hình ở cấp hệ thống, một nguồn dữ liệu ODBC có thể được cấu hình để sử dụng bộ ký tự của cơ sở dữ liệu de SQL Server hoặc chuyển đổi thành bộ ký tự máy tính khách.

+0

Nếu tôi sử dụng cấu hình ODBC chỉ và kết nối với PHP PDO odbc, tôi không thể nhận được dữ liệu UTF-8. –

2

Khi đặt mã hóa ký tự thành UTF-8, bạn cũng cần phải mã hóa truy vấn dưới dạng UTF-8 và giải mã kết quả. Bộ ký tự nói với trình điều khiển rằng bạn nói UTF8 nguyên bản. Như vậy, bạn cần phải chuyển đổi UTF8 trở lại những gì PHP hiểu (ASCII hoặc mbstring).

$dsn = "odbc:DRIVER={SQL Server};SERVER=$hostname;DATABASE=$database;charset=UTF-8"; 
$pdo = new PDO($dsn,$username,$password); 
$sql = utf8_encode("SELECT text FROM atable"); 
$result = $PDO->query($sql); 
while($data = $result->fetchObject()){ 
    $values[] = utf8_decode($data->text); 
    // possibly also: $values[] = utf8_decode($data[utf8_encode('text')]); 
} 
dpm($values); 
+0

Vâng, như đã nói, điều này được thực hiện từ một mô-đun Drupal. Drupal mong đợi tất cả các chuỗi được mã hóa UTF-8, nó cũng xuất ra các trang của nó với bộ mã hóa của chúng được đặt thành UTF-8. Khi nguồn dữ liệu ODBC được cấu hình để sử dụng UTF-8 (xem câu trả lời của tôi), PDO trả về dữ liệu được mã hóa UTF-8 được xuất ra đúng với hàm dpm(). Việc gọi utf8_decode() trên dữ liệu từ PDO sẽ tạo ra các kết quả đầu ra bị cắt xén vì chuỗi sẽ được hiển thị trong một trang được mã hóa UTF-8. –

+0

Cảm ơn, đã làm việc hoàn hảo cho tôi.! – Dharmavir

0

Bạn có thể sử dụng mã này để sửa chữa vấn đề của bạn:

$result = odbc_exec($this->con, $sql);  
$data = fetch2Array($result); 

private function fetch2Array($result){  
    $rows = array(); 

    while($myRow = odbc_fetch_array($result)){ 
     $rows[] = $this->arrayToUTF($myRow); 
    } 
    return $rows; 
} 

private function arrayToUTF($arr){ 
    foreach ($arr as $key => $value) { 
     $arr[$key] = utf8_encode($value); 
    } 
    return $arr; 
} 
+0

Yêu cầu câu hỏi cho một giải pháp với PDO, câu trả lời này không sử dụng PDO. Ngoài ra, các giải pháp được đề xuất là dư thừa với một năm trước đây của Veggivore (ví dụ: chuyển đổi các giá trị bằng utf8_encode()). –

0

Bạn có thể sử dụng mã này để sửa chữa vấn đề của bạn:

Đầu tiên bài viết dữ liệu Chuyển đổi

'$word = iconv("UTF-8","Windows-1254",$_POST['search']);' 

Và đọc dữ liệu Chuyển đổi

while($data = $result->fetchObject()){ 
    $values[] = iconv("Windows-1254", "UTF-8",$data->text)); 
} 

SQL Chuỗi

$sql = "SELECT * FROM yourtables WHERE text LIKE '%{$word}%'"; 
or 
$sql = "SELECT * FROM yourtables"; 
Các vấn đề liên quan