Voor mijn website maak ik gebruik van een MySQL database. Op deze database heb ik volledige schrijf / lees en bewerk rechten. Al snel was mijn database onderwerp van gesprek. Er werd gerefereerd naar het volgende artikel. Helaas moet ik zeggen dat ik dat artikel niet helemaal kan volgen. Vandaar dat ik jullie wil vragen even te kijken naar mijn lees en schrijf functie. Hopelijk zien jullie de oplossing wel.
This function is identical to htmlspecialchars() in all ways, except with htmlentities(), all characters which have HTML character entity equivalents are translated into these entities.
If you're wanting to decode instead (the reverse) you can use html_entity_decode().
Waarom ga je het ook eerst decoden om nadien weer te encoden? Dan vraag je toch om problemen? niet?
//edit:
irc schreef:
<Martijn> Als ik die functie apart neem, dus gewoon los, zonder DB connection, en ik geef als input één dan doet die functie gewoon goed zijn werk. En dat terwijl de DB dezelfde input geeft. Ontzettend vaag verhaal dus, maar het is toch echt zo.
Kan je iets meer code geven dan? (heb dit hier zo even bijgezet zodat de rest het probleem ook wat beter kan begrijpen)
UPDATE3: Het zit hem waarschijnlijk in het plaatsen van de data in de database en het lezen. De functie htmlentities werkt wel gewoon stand-alone. Een foutieve server-configuratie lijkt mij daarom bijna onmogelijk.
UPDATE5: Htmlentities in de write functie is ook niet zo'n succes. Daarom heb ik de htmlentities toch maar weer terug geplaatst in de read functie. Helaas nogsteeds niet met het gewenste resultaat.
UPDATE7: Bij de invoer maak ik nu alleen nog gebruik van mysql_real_escape_string en bij de uitvoer van htmlentities. Ook dit brengt niet de oplossing.
Heb je het nu al eens op een andere server geprobeerd zoals ik je gisteren adviseerde? Zo kan je uitsluiten dat het aan je webserver/database server ligt, of zo kan je erachter komen dat het probleem zich daar bevindt...
Een xampp/usbwebserver/... volstaat hier voor (en die hebben als voordeel dat je ze enkel moet extracten & runnen )
Het heeft niets met mijn DB te maken ben ik al achter. Ik heb de volgende code gebruikt om dat te testen. Als input in de textarea gaf ik weer het woord èèn, als output kreeg ik èèn.
Richard - 06/03/2009 16:51 (laatste wijziging 06/03/2009 16:52)
Crew algemeen
Ja, dat is nogal logisch aangezien je geen charset of wat dan ook meegeeft..
Als je het allemaal goed wil hebben zal _ieder_ aspect van applicatie UTF8 moeten gebruiken:
- database (ook de verbinding: SET NAMES 'utf8')
- tekstbestanden
- output
Ten eerste, alle kolommen in al je tabellen stel je in op utf8. (MySQL: utf8_unicode_ci ofzo)
Als je nu verbinding maakt met de database, voer je direct de query "SET NAMES 'utf8'" uit, zo kan de verbinding er ook goed mee overweg.
Iedere pagina waarop je nu data laat zien of data laat invoeren, stuur je als header mee: header('Content-Type: text/html;charset=utf8');
Daarnaast stuur je een meta http-equiv mee:
<meta http-equiv="Content-Type" content="text/html;charset=utf8" />
In principe zou alleen de header genoeg moeten zijn, maar zo weet je het tenminste zeker. :-)
Ik heb het even geprobeerd met mijn test-scriptje. Helaas, maar toch is het waar, deze oplossing werkt ook niet. Tenzij ik natuurlijk iets niet helemaal goed doe.
krijg je met dat script geen error??? (headers allready sent)
http://php.net/header schreef:
Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include(), or require(), functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.
Ja, je hebt gelijk, had in mijn htaccess error onderdrukking ingeschakeld. Maar werkt nog niet.
UPDATE: Het probleem bevindt zich in de server configuratie. Apache2Triad runt mijn voorbeeld zonder problemen. Heeft iemand misschien een idee waar ik moet zoeken? php.ini, httpd.conf, apache2.conf?
OPLOSSING: utf8_decode na het uitlezen van de DB gebruiken.
mod edit: dit is waarschijnlijk niet de goede oplossing
Thomas - 11/01/2015 19:01 (laatste wijziging 11/01/2015 19:03)
Moderator
Hiermee haal ik wellicht oude koeien uit de sloot, maar deze encoderingsproblemen zijn nog redelijk actueel.
Als je utf8_decode moet toepassen op data uit een utf8-tabel om deze af te drukken in een UTF-8 document, dan houdt dit waarschijnlijk in dat de gegevens in je database dubbel ge-encodeerd zijn. Dit werd waarschijnlijk weer veroorzaakt doordat je geen character set had geselecteerd op het moment van wegschrijven van je data.
MySQL is zelf redelijk intelligent als het gaat om omzettingen tussen verschillende encoderingen. Stel je hebt een utf8-tabel, maar je hebt geen character encoding meegegeven bij het maken van een verbinding met je database. Er is dan een grote kans dat deze de default character encoding pakt (latin1). Je brongegevens uit je formulier waren al UTF-8 door je header(), meta-tag en mogelijk accept-charset property in je form-tag. Maar MySQL is (nog steeds) in de veronderstelling dat data die naar je database wordt gestuurd latin1-data is. En MySQL ziet dat je dat in een utf8 database-tabel of -kolom probeert weg te schrijven. Dus zet MySQL deze data (nogmaals) om naar utf8. Je data staat dus vervolgens dubbel ge-encodeerd in je database.
Als je dan vervolgens je data weer probeert uit te lezen (zonder het instellen van een character set) dan ziet MySQL dat je bron-data (in je database) utf8 is, maar je connectie is / verwacht latin1. MySQL zal dan dus zelf al een utf8-decodering doen.
In de oorspronkelijke opzet zal dat dus (lijken te) werken, want je gaat dan weer terug van een dubbele encoding naar een enkele encoding. Alles lijkt dan goed te gaan... totdat je je connectie credentials repareert .
Repareer je echter je connectie door het instellen van de juiste te gebruiken character encoding door gebruikmaking van een _set_charset() functie, dan zal MySQL niets omzetten bij schrijven naar / lezen uit de database. MySQL is dan al verbonden met gebruikmaking van utf8-encodering, en de database-tabellen en -kolommen zijn ook utf8 - er hoeft dan simpelweg niets vertaald te worden.
Tot slot, als je speciale karakters wilt neutraliseren bij het afdrukken in een HTML-document, zodat deze geen speciale betekenis hebben in de HTML-context dan kun je hiervoor htmlentities() of (wellicht beter) htmlspecialchars() gebruiken. Hierbij moet je wel een character-encoding meegeven (derde parameter). Tot PHP-versie 5.4 wordt verondersteld dat dit ISO-8859-1 (min of meer equivalent met latin1 in MySQL) is. Het is beter om expliciet een character encoding mee te geven.
In dit topic is het probleem waarschijnlijk in eerste instantie dat de data in de database niet op de goede manier is weggeschreven. Als je allerlei (extra) goocheltruuks moet uithalen om e.e.a. fatsoenlijk af te drukken dan is er ergens iets mis. De eerste stap bij het oplossen van dit soort problemen lijkt mij het creëren van een kloppende uitgangssituatie. Dat wil zeggen: schakel ALLE character encoderingen gelijk:
- die van je HTML-document
- die van je database-connectie
- die van je database tabellen- en kolommen-structuur
- en als laatste (en wellicht belangrijkste), die van de encodering van je opgeslagen data
Het controleren van de character-encoding van opgeslagen data kan relatief eenvoudig. Aan de MySQL-zijde kun je data door de MySQL-functie HEX() halen. Aan de PHP-zijde kun je de data door de PHP-functie bin2hex() halen. Als de uitkomsten van deze twee functie-aanroepen op dezelfde brondata verschillend zijn betekent dit dat er ergens vertalingen (tussen character encoderingen) hebben plaatsgevonden, waarschijnlijk doordat je bij het maken van een database-connectie geen (of de verkeerde) character encoding had geselecteerd.
Deze twee functies zou je ook kunnen gebruiken om te kijken of de weggeschreven data wel de juiste character encoding heeft, of dat de data zelf corrupt is, deze functies zijn namelijk niet character encoding aware, oftewel, geven altijd dezelfde "uitkomst" op dezelfde input ongeacht de op dat moment gebruikte character encoding (hetzij in de database, hetzij in je PHP-script).