Off-topic:
Nouja, ergens is er wat voor te zeggen; iedereen heeft een beperkte hoeveelheid tijd tot z'n beschikking, al dan niet professioneel, waarin je iets wilt neerzetten. Encoding is alleen wel heel erg belangrijk, zonder dat je het in eerste instantie doorhebt, het is dan ook niet zo heel vreemd dat PHP6 volledig Unicode moest zijn. Helaas bleek dat zo lastig dat de ontwikkelaars PHP6 maar hebben overgeslagen. Dus zijn we toch weer op onzelf aangewezen.
Waarom je het wel wilt/moet weten:
Wanneer je iets programmeert of zelfs maar typt in een tekstverwerker heb je al onbewust met encoding te maken. Dat gaat goed zolang de encoding hetzelfde blijft. Je krijgt met encoding te maken bijvoorbeeld:
- als je even vlug een site klust en later de vraag naar boven komt om een webwinkel te bouwen en het euro-teken nodig is
- je wilt je site aanvullen met AJAX, en dan blijkt de benodigde encoding (Unicode) niet te passen op de default encoding van je OS cq. PHP (Latin1).
- je wilt maar zelfs iets inlezen van een CSV, tekstbestand met BOM, of zelfs XML schrijven via SimpleXML, XMLWriter of DOMDocument, die laatsten willen allemaal Unicode als input.
- je wilt iets lezen of wegschrijven naar je MySQL-database met een andere encoding
In al deze gevallen krijg je te maken met het overzetten van de ene encoding naar de andere, oftewel transcoding. Als je je daar niet bewust van bent, gaan de dingen zeker verkeerd (data wordt verkeerd geinterpreteerd of erger - karakters die niet naar de doelencoding worden gemapped raken domweg kwijt), en dat is jammer omdat het vooraf relatief simpel voorkomen had kunnen worden. Dan hoef je niet achteraf nog eens in alle voorkomende gevallen met str_replace() de diakritische tekens te vervangen voor HTML-entities, dat kost extra en dus onnodige resources, niet alleen van de CPU maar ook van je eigen ontwikkeltijd. Jij en je klant zijn uiteindelijk beter af als je van te voren aandacht hebt voor encoding.
Later (zeg: 6 maanden geleden) dacht ik van: alles UTF8 (of LATIN1, wat dan ook).
Het beste kan je Unicode gebruiken gebruiken voor je website of -applicatie, UTF-8 is de default van HTML5.
Korte checklist:
- je kunt je PHP files opslaan in UTF-8 omdat UTF-8 ASCII-compatible is zonder BOM of Byte Order Mark. Een BOM is niet van toepassing op UTF-8 en het zorgt dat er te snel HTTP headers worden verstuurd, dus dat willen we niet.
- je geeft encoding aan via HTTP-headers
header('Content-Type: text/html; charset="UTF-8"');
- je checkt de input die de browser naar PHP stuurt of de strings wel UTF-8 compliant zijn (*)
Bijvoorbeeld met een soort van is_utf8() -functie van een library als
Portable UTF-8
- je gebruikt utf8mb4 als encoding voor tabellen en kolommen
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- je stelt de verbinding met de database via mysqli of PDO in als UTF-8 (om automatische transcoding via de driver te voorkomen)
$db = new mysqli(...);
$db->set_charset('utf8mb4');
$db->query('SET NAMES "utf8mb4" COLLATE "utf8mb4_unicode_ci";');
- je moet een
lettertype gebruiken dat de Unicode karakters ondersteunt die je wilt zien
Bij het programmeren in PHP moet je vervolgens op twee dingen blijven letten:
1.) De oudere, SBCS-functies (Single Byte Character Support) zoals strlen() en alle andere werken op byte-niveau, ze zijn niet geschikt voor UTF-8. Je moet dan de MBCS-functies (Multi Byte Character Support) gebruiken zoals mb_strlen(). PHP biedt niet voor alle SBCS-functies een MBCS-variant. Via het internet zijn libraries te vinden die PHP aanvullen.
2.) De nodige MBCS-functies van PHP werken alleen met de eerste Unicode plane en niet met de overige planes, de MBCS-functies zijn dus niet volledig Unicode compliant. Dat bemoeilijkt bijvoorbeeld gebruik van emoji en vele andere Unicode karakters. Gelukkig hebben we de meeste van die karakters niet nodig, en zijn er omwegen met notatie in andere vormen die weer ASCII-compliant zijn, en extra ruimte nodig hebben.
Hopelijk biedt PHP7 volledige ondersteuning voor Unicode, maar ik vermoed van niet anders hadden ze dat wel groots aangekondigd.
(*) Dit punt is waar het mij om te doen is bij het controleren van de $_SERVER['REQUEST_METHOD'] die door de browser wordt ingesteld. Gelukkig blijkt de tekst 'POST' altijd hetzelfde te zijn in zowel ASCII als Latin1 als Unicode.