Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Character encoding issue with PDO_ODBC

Tags:

php

pdo

odbc

drupal

When accessing a Microsoft SQL Database from PHP using PDO_ODBC with the following code, I have an encoding issue. When outputed the text from the DB is garbled.

$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
(source: bayimg.com)

This is done from a Drupal module. Everything in Drupal is made to work with UTF-8. The cleanest solution would be to able to retrieve the data from the database in UTF-8 or to convert it UTF-8 before outputting.

I tried these without any success

  • $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') after new PDO(...)
  • $pdo->exec('SET CHARACTER SET utf8'); after new PDO(...)

PS: The code is currently developped on Windows but it has to work on GNU/Linux too.

like image 878
Pierre Buyle Avatar asked Aug 12 '10 11:08

Pierre Buyle


2 Answers

When running on Linux and using the FreeTDS driver, the charset for the client can be configured with the client charset setting in the freetds.conf file. In order for the freetds.conf file to be used when using PDO ODBC and unixODBC, one needs to configure the ODBC datasource using ODBC-combined configuration. When ODBC-only configuration is used to configure the ODBC datasource, the file freetds.conf is not used. With this I was able to retrieve and insert UTF-8 data from/into the MS SQL Server database.

Being a Linux/Unix guy, I was unable to understand/find a way how to configure the charset used when PDO ODBC is used on Windows. My vague understanding is that when configured at the system level, an ODBC datasource can be configured to use either de SQL Server database's charset or convert to the client computer charset.

like image 98
Pierre Buyle Avatar answered Oct 20 '22 14:10

Pierre Buyle


When setting the character encoding to UTF-8, you will also need to encode your queries as UTF-8 and decode the results. The charset is telling the driver that you speak UTF8 natively. As such, you need to convert the UTF8 back to what PHP understands (ASCII or 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);
like image 1
Veggivore Avatar answered Oct 20 '22 14:10

Veggivore