Languages

User login


com treballar amb utf-8 en entorn web (MySQL i PHP)


us heu trobat mai que escriviu un text amb accents, dièresis, c trencades i d'altres caràcters que no siguin de l'estàndard ansi i que llavors es representin amb caràcters estranys?

això és degut al joc de caràcters (o charset en anglés), un altre aspecte a tenir en compte és la ordenació d'aquests caràcters (o collation en anglés)

jocs de caràcters i ordenacions

introducció

com ja sabreu els caràcters es guarden a memòria com un conjunt de uns i zeros que al cap i a la fi seràn la representació binària de un número, doncs bé, els jocs de caràcters (UTF-8, ISO-8859-1, JIS, CP437) ens defineixen aquesta relació, a cada caràcter se li asigna un número (els famosos números de la taula ascii per exemple)

l'ordenació dels caràcters són regles amb les quals s'estableixen relacions entre els diferents símbols del joc de caràcters, així per exemple en un joc de caràcters amb 4 símbols ('a','b','A' i 'B') per saber si 'a' i 'b' són el mateix es miraria la codificació (el nº binari) dels símbols (les lletres) i s'establiria una relació de menor que, igual que o més gran que. Evidentment l'ordenació de qualsevol joc de caràcters és molt més complexe

per a cada joc de caràcters i ha múltiples ordenacions, però aquestes ordenacions son específiques del joc de caràcters, és a dir, si fas servir el joc de caràcters JIS (japonés) no pots fer servir una ordenació utf8_general_ci o una ordenació latin1_swedish_ci, apart que les aplicacions ja haurien de dir-te que no pots, les ordenacions o comparacions que faries tindrien resultats imprevisibles

exemples

quan nosaltres entrem un text aquest es guarda al disc traduit a números segons la codificació a la que treballi el nostre SO, escriptori, la base de dades on guardem les dades, el programa amb el que treballem, etc ... i a l'hora de representar aquestes dades també fem servir el joc de caràcters amb el que treballi el programa que ens el mostra

els problemes sorgeixen quan un fitxer guardat en un linux (la inmensa majoria de distribucions ja fan servir UTF-8) el veu un usuari de windows (latin1 o altrament dit ISO-8859-1 o -15 si és amb el símbol de l'euro), aquest veurá caràcters estranys, no se li farà el salt de línia (tot i que això ja és el format que fa servir cada S.O. per dir quan és el final de línia)

entorn web

mysql

si ens centrem en les base de dades MySQL 4.1.x o 5.x (versions anteriors no permeten triar el joc de caràcters i l'ordenació) ens trobem amb un problema multiplicat per 5, perquè la gent de MySQL van decidir que poguessis determinar el joc de caràcters i l'ordenació d'aquests al servidor, la base de dades, la taula, cada camp de text i fins i tot la connexió!

ja a tall personal i vaig estar batallant molt de temps per aconseguir que la base de dades em treballés del tot amb UTF-8, fins que una bona lectura de tot el capítol 10 de la documentació del MySQL, em va fer veure la llum (si és que les documentacions ho solucionen tot, o casi)

si es vol treballar amb UTF-8 (o qualsevol altre codificació) a tots els nivells l'únic que hem de fer és posar en els nostres scripts php o (el llenguatge que sigui que interactua amb la base de dades) just després d'haver fet la connexió a la base de dades una sentència del tipus:

SET character_set_client=UTF8, character_set_connection=UTF8, character_set_database=UTF8,

character_set_results=UTF8, character_set_server=UTF8, character_set_system=UTF8;

hi ha un salt de línia per la formatació de la pàgina, seria tot seguit

i per les ordenacions:

SET collation_connection=utf8_general_ci, collation_database=utf8_general_ci, collation_server=utf8_general_ci;

les sentències SQL "SET" serveixen per modificar variables d'entorn del mysql, al executar una sentència d'aquest tipus li estàs dient "a partir d'ara tot el que et vingui li apliques aquestes variables d'entorn"


un mètode abreujat i que no modifica totes les variables referents a jocs de caràcters i ordenacions és:
SET NAMES utf8;

per tant, és una bona idea posar aquestes sentències en el mateix script que facis la connexió, així segur que tot funcionarà tal i com ha d'anar (a no se que durant l'execució, pels motius que siguin, s'hagi de canviar de codificació) en aquest cas hauries de executarl la sentència "SET NAMES" abans de enviar-li els query's amb la nova codificació (o els paràmetres que hagis canviat) i tornar a deixar els que tenies abans (si es que interessa)

dir que hi han abreviatures per canviar-ho, però que no fan un canvi a totes les variables sinó només a unes quantes (se suposa que les que canvien son les necessàries, però fent-ho així segur que no hi ha cap error de codificació i segons com es miri el rendiment de la base de dades serà més alt perquè no tindrà d'estar perdent el temps canviant de joc de caràcters per anar a buscar i tornar els resultats)

tot i haver posat totes variables del MySQL a utf8 no vol dir que els teus formularis fets amb php et retornin les dades correctament,  un cop resolta la base de dades el que falta és que el teu navegador també treballi amb utf8 i sobretot que també el php i treballi

php

per canviar el navegador, si fas servir firefox pots canviar-ho anant al menú Visualitzar->codificació de caràcters i allà tries UTF8 o la codificació que desitjis (apart si vas a les preferències pots definir un joc de caràcters per defecte)

per fer que els scripts amb php mostrin les pàgines amb php li pots enviar un header amb la línia següent:

header('Content-Type: text/html; charset=utf-8');

llavors ja només ens caldrà modificar el php.ini (fitxer de configuració del php) i afegir-hi les línies (pel mòdul iconv i exif):

busqueu i substituiu adeqüadament
default_charset = "UTF-8"

[exif]
exif.encode_unicode = UTF-8

[iconv]
iconv.input_encoding=UTF-8
iconv.output_encoding=UTF-8
iconv.internal_encoding=UTF-8

recordeu que perquè això funcion heu de compilar (o bé descarregar-vos els paquets) necessaris perquè el php doni suport al iconv i al exif (afegint --enable-exif i enable-iconv a la comanda de configuració del php ja n'hi haurà prou)

altre cop tenim una doble ventatja si els posem tots tres a UTF-8, ens assegurem de que treballarem a UTF-8 tot el temps i no hi haurà pèrdua en alguna conversió i augmentem el rendiment al no haver de fer que el php hagi d'anar canviant de joc de caràcters

teniu en compte que si per algun motiu o altre heu de tenir activat el mbstring us donarà problemes

Comentaris

Comment viewing options

Selecciona la vostra manera preferida de visualitzar els comentaris i feu clic en "Desa la configuració" per activar els canvis.

Possibles problemes

Què passaria si s'indroduiren les dades des d'un navegador configurat amb una codifiació diferent (per exemple iso-8859-1, la codificació habitual).

És a dir: si faig un sistema de comentaris a la meva pàgina, i ho tinc tot funcionant amb utf-8 (php mysql i el meu navegador) com puc estar segur que el que escriguen els usuaris es tractarà correctament?

gràcies per preguntar! pots

gràcies per preguntar!

pots incloure un header al php i dir-li que sigui amb utf

 header("Content-type: text/html; charset=utf-8");

 pots incloure un meta-tag a la secció del "head"

 meta http-equiv="Content-Type" content="text/html; charset=utf-8"

 i també pots posar que en els formularis s'accepti un determinat joc de caràcters

 form accpet-charset="utf-8" .....

 i també tens funcions del php per passar textos a utf-8

Aleshores....

Gràcies per respondre tan prompte!

Aleshores si indique en el content-type (tant al header com amb meta) i en l'accept-charset del formulari que treballe amb utf-8, les dades m'arribaran en utf?

Si no és així, per a que aprofita el accept-charset del formulari?

home, en principi si que ha

home, en principi si que ha de ser així, que tu retorni amb utf, sinó seria una tonteria que tu permetessin, jo em referia a que alguns navegadors vells no deuen tenir implementat l'utf8 i llavors qui sap


pots fer un javascript que envii un comentari a l'usuari dient-li, però fes proves de quins navegadors van i quins no, mira si trobes alguna web que digui el suport dels navegadors

PHP i UTF-8

Aquest tema m'interessa molt, sobretot a PHP. Actualment tinc força problemes amb PHP i UTF-8. Tinc els script codificats com a UTF-8, però m'he adonat que les funcions de tractament de textos tenen problemes amb UTF-8.

Per exemple, aquest codi:
{codi}
echo iconv_get_encoding("internal_encoding");
$var = 'ADÉU';
echo $var = strtolower($var);
{/codi}

Retorna això:
{retorn}
UTF-8
ad?u
{/retorn}

Com pot ser? no em passa bé el text a minuscules si té accents! I tot està a UTF-8, l'arxiu PHP també, i envio un header amb:
header('content-type: text/html; charset=utf-8');

I el navegador està també amb UTF-8.

A php.ini tinc:
{php.ini}
[iconv]
iconv.input_encoding=UTF-8
iconv.output_encoding=UTF-8
iconv.internal_encoding=UTF-8
{/php.ini}

Tal com surt al article.

Algú em pot donar un cop de mà? Gràcies!

si faig un "cat

si faig un "cat /etc/php/php.ini | grep UTF" em surt això: default_charset = "UTF-8" exif.encode_unicode = UTF-8 iconv.input_encoding=UTF-8 iconv.internal_encoding=UTF-8 iconv.output_encoding=UTF-8 el teu SO te suport per UTF-8 ? has compilat (o agafat els paquets de) el php amb suport per a l'iconv i l'exif (aquest últim me l'havia deixar ara ho afegeixo a la documentació)

Faig servir Windows XP, no

Faig servir Windows XP, no sembla pas tenir cap problema amb UTF-8. Al php.ini hi tinc la secció de "iconv" bé, com també la de "exif". Però resulta que a Windows per a fer servir l'extenció php_exif.dll, cal tenir activada l'extenció php_mbstring.dll:

"Windows users must also have the mbstring extension enabled."
http://www.php.net/manual/es/ref.exif.php

Si activo la mbstring, puc fer servir les funcions mb_*(), amb les quals, si sembla funcionar el tractament amb cadenes de text, per exemple, mb_strtolower(). I això és el que no entenc, tothom qui fa págines multi-lingues, fa servir les funcions estàndard amb UTF-8, o les de mbstring?
He donat un cop d'ull al codi de alguns CMS coneguts, i tots els arxius PHP no estan pas codificats com a UTF-8. Com coi s'ho fan després per a poder ser traduits a un munt d'idiomes? :?

Per què a tu et funciones bé les funcions com strtolower() amb UTF-8, oi?

no cal pas

si el que vols fer és un strtolower() no cal que sigui utf, ni cap joc de caràcters en concret la funció aquesta mira els caràcters que sigui majúscula i els passa a minúscula, i tots els jocs de caràcters (llatins almenys) tenen minúscula i majúscula jo el mbstring també el tinc compilat, però és això, només es necessari per a windows (si ho posen a la seva documentació serà per alguna cosa ;) ), però només tinc activada la opció (al php.ini): [mbstring] mbstring.language = Japanese

Bé, en realitat és al

Bé, en realitat és al revés, vull emprar strtolower() a un text UTF-8, però no hi ha manera. :-(

doncs no se :S tampoc ho se

doncs no se :S tampoc ho se tot del php ... i a més des d'un windows .... as provat altres pàgines que siguin amb utf i tot funcioni? prova d'anar aquí http://l10n-status.gnome.org/gnome-2.12/PO/evince.gnome-2-12.ca.po i mira que tot et surti correctament, accents i demés

La web del Gnome em surt

La web del Gnome em surt correcte, amb accents i "ç".

Em baixaré el PHP 5.0.5 que acava de sortir, a veure si canviant la versió i php.ini em funciona. :-?

Gràcies per les respostes!

uff el php5 canvia moooolta

uff el php5 canvia moooolta cosa ... si tens bases de dades mysql haurás de reescriure totes les consultes, per això jo encara vaig amb php4 sort i ja comentarás què tal (registra't a la pàgina que es gratis i així podràs veure millor les coses, i apart sabré a qui m'adreço :P )

He arribat a la conclusió,

He arribat a la conclusió, de que aquest comportament és normal. Les funcions "estàndards", són per a treballar amb codificacions d'un byte per caràcter. Tant se val si és Latin-1, com si és per a ciríl·lic o grec.
Però si es vol treballar amb text UTF-8, no queda més remei que fer-ho amb les funcions d'mbstring, (per això mateix és diu multi-byte).

Quant a PHP5, cap problema, fins ara feia servir una versió anterior de PHP5.

Un dia d'aquest potser em registro, però és que jo de tema wifi... poc puc aportar. :-(

doncs aporta al comesfa :P

doncs aporta al comesfa :P