php ms-access pdo utf-8 odbc

php - No se pueden recuperar caracteres acentuados UTF-8 de Access a través de PDO_ODBC



ms-access (2)

Estoy tratando de convertir una base de datos de acceso en MySQL. Todo funciona perfectamente, espere una llave inglesa grande ... Si el db de acceso tiene caracteres no estándar, no funcionará. Mi consulta me dirá:

Incorrect string value: ''/xE9d''

Si hago eco directamente del texto de las filas que tiene el carácter ''inválido'', obtengo un signo de interrogación en un cuadrado negro en mi navegador (por lo que é se convertiría en ese símbolo simbólico no válido en el eco).

NOTA: Eso mismo aceptará, guardará y mostrará la "é" muy bien en un cuadro de texto que se utiliza para titular esta carga db. Además, si ''guardo como'' la página y la vuelvo a abrir, la ''é'' se muestra correctamente ...

Así es como me conecto:

$conn = new PDO("odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$fileLocation;SystemDB=$securefilePath;Uid=developer;Pwd=pass;charset=utf;");

He intentado numerosas cosas, que incluyen:

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

Cuando pruebo un ''CurrentDb.CollatingOrder'' en el acceso, me dice 1033 aparentemente que es dbSortGeneral para "orden de clasificación en inglés, alemán, francés y portugués".

¿Qué está mal? Es casi como si el PDO me estuviera enviando una recopilación de mi navegador y PHP no comprende completamente.


El problema

Cuando se utilizan características ODBC PHP nativas (PDO_ODBC o las funciones odbc_ más odbc_ ) y el controlador ODBC de Access, el texto no está codificado en UTF-8, aunque se almacena en la base de datos de Access como caracteres Unicode. Entonces, para una tabla de ejemplo llamada "Equipos"

Team ----------------------- Boston Bruins Canadiens de Montréal Федерация хоккея России

el código

<?php header(''Content-Type: text/html; charset=utf-8''); ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Access character test</title> </head> <body> <?php $connStr = ''odbc:'' . ''Driver={Microsoft Access Driver (*.mdb)};'' . ''Dbq=C://Users//Public//__SO//28311687.mdb;'' . ''Uid=Admin;''; $db = new PDO($connStr); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT Team FROM Teams"; foreach ($db->query($sql) as $row) { $s = $row["Team"]; echo $s . "<br/>/n"; } ?> </body> </html>

muestra esto en el navegador

Boston Bruins Canadiens de Montr�al ????????? ?????? ??????

Las soluciones fáciles pero incompletas

El texto devuelto por Access ODBC en realidad coincide con la codificación de caracteres de Windows-1252 para los caracteres en ese conjunto de caracteres, por lo que simplemente cambia la línea

$s = $row["Team"];

a

$s = utf8_encode($row["Team"]);

permitirá que la segunda entrada se muestre correctamente

Boston Bruins Canadiens de Montréal ????????? ?????? ??????

pero la función utf8_encode() convierte de ISO-8859-1 , no de Windows-1252 , por lo que algunos caracteres (especialmente el símbolo del euro ''€'') desaparecerán. Una mejor solución sería usar

$s = mb_convert_encoding($row["Team"], "UTF-8", "Windows-1252");

pero eso aún no resolvería el problema con la tercera entrada en nuestra tabla de muestra.

La solución completa

Para obtener soporte completo para UTF-8, necesitamos usar COM con ADODB Connection y objetos Recordset como este

<?php header(''Content-Type: text/html; charset=utf-8''); ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Access character test</title> </head> <body> <?php $connStr = ''Driver={Microsoft Access Driver (*.mdb)};'' . ''Dbq=C://Users//Public//__SO//28311687.mdb''; $con = new COM("ADODB.Connection", NULL, CP_UTF8); // specify UTF-8 code page $con->Open($connStr); $rst = new COM("ADODB.Recordset"); $sql = "SELECT Team FROM Teams"; $rst->Open($sql, $con, 3, 3); // adOpenStatic, adLockOptimistic while (!$rst->EOF) { $s = $rst->Fields("Team"); echo $s . "<br/>/n"; $rst->MoveNext; } $rst->Close(); $con->Close(); ?> </body> </html>


Un poco más fácil de manipular los datos. (Matriz de matriz).

function consulta($sql) { $db_path = $_SERVER["DOCUMENT_ROOT"] . ''/database/Registros.accdb''; $conn = new COM(''ADODB.Connection'', NULL, CP_UTF8) or exit(''Falha ao iniciar o ADO (objeto COM).''); $conn->Open("Persist Security Info=False;Provider=Microsoft.ACE.OLEDB.12.0;Jet OLEDB:Database Password=ifpb@10510211298;Data Source=$db_path"); $rs = $conn->Execute($sql); $numRegistos = $rs->Fields->Count; $index = 0; while (!$rs->EOF){ for ($n = 0; $n < $numRegistos; $n++) { if(is_null($rs->Fields[$n]->Value)) continue; $resultados[$index][$rs->Fields[$n]->Name] = $rs->Fields[$n]->Value; echo ''.''; } echo ''<br>''; $index = $index + 1; $rs->MoveNext(); } $conn->Close(); return $resultados; } $dados = consulta("select * from campus"); var_dump($dados);