„ und “ in MySQL Schreiben
Amerlander
- php
0 Tom2 dedlfix0 hotti0 Amerlander0 dedlfix0 Amerlander2 dedlfix
Hallo,
ich habe eine Seite, in welcher User selbst Einträge einstellen können.
Wenn in einem der Einträge aber ein richtiges Anführungszeichen (nur Englisch oder Deutsch, die Französischen gehen) vorkommt, dann bricht MySQL den Eintrag ab.
Aus
"Das ist ein „Beispieltext“"
Wird in die Datenbank dann nur das eingetragen:
"Das ist ein "
Ich verwende HTML htmlentities() und habe es auch schon mit
$text = str_replace("„","„",$text);
versucht.
Das bringt leider nichts, da das Zeichen einfach nicht ersetzt wird. Wenn ich dort die Zeichen austausche (beispielsweise "a" durch "b" ersetze) klappt es.
Wenn ich vor dem Speichern "echo $text;" mache wird mir auch der ganzen text ausgegeben, nur wird er eben nicht richtig gespeichert.
Die Seite auf welcher das Formular ist ist in Utf-8.
Warum wandelt mir htmlentities() diese Zeichen nicht in die entsprechenden HTML Codes um und warum klappt das ersetzen mit str_replace auch nicht?
was habt ihr für Tipps für mich um das Problem zu lösen?
lg
Amerlander
Hello,
ich habe eine Seite, in welcher User selbst Einträge einstellen können.
Wenn in einem der Einträge aber ein richtiges Anführungszeichen (nur Englisch oder Deutsch, die Französischen gehen) vorkommt, dann bricht MySQL den Eintrag ab.
Aus
"Das ist ein „Beispieltext“"Wird in die Datenbank dann nur das eingetragen:
"Das ist ein "Ich verwende HTML htmlentities() und habe es auch schon mit
$text = str_replace("„","„",$text);
versucht.
Und warum verwendest Du nicht die Escapefunktion, die dafür vorgesehen ist?
http://de3.php.net/manual/en/function.mysql-escape-string.php
http://de3.php.net/manual/en/function.mysql-real-escape-string.php
Und lies bitte den Artikel
http://wiki.selfhtml.org/wiki/Artikel:Kontextwechsel
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Und warum verwendest Du nicht die Escapefunktion, die dafür vorgesehen ist?
Nebst dessen, diese beiden Zeichen sind nix, was man irgendwie escapen müsste.
Hello,
Und warum verwendest Du nicht die Escapefunktion, die dafür vorgesehen ist?
Nebst dessen, diese beiden Zeichen sind nix, was man irgendwie escapen müsste.
Man muss immer escpapen, wenn es sich um unbegrenzte variable Eingaben handelt (z.B. Benutzereingaben)!
Oder bist Du da etwa anderer Meinung?
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Und warum verwendest Du nicht die Escapefunktion, die dafür vorgesehen ist?
Nebst dessen, diese beiden Zeichen sind nix, was man irgendwie escapen müsste.
Man muss immer escpapen, wenn es sich um unbegrenzte variable Eingaben handelt (z.B. Benutzereingaben)!
Oder bist Du da etwa anderer Meinung?
Nein, selbstverständlich nicht - nur liegt hier der Fehler klar wo anders. Etwa bei der Zeichencodierung - es ist verdächtig, wenn nach dem betreffenden Zeichen einfach "nix" mehr kommt.
Hello,
Und warum verwendest Du nicht die Escapefunktion, die dafür vorgesehen ist?
Nebst dessen, diese beiden Zeichen sind nix, was man irgendwie escapen müsste.
Man muss immer escpapen, wenn es sich um unbegrenzte variable Eingaben handelt (z.B. Benutzereingaben)!
Oder bist Du da etwa anderer Meinung?
Nein, selbstverständlich nicht - nur liegt hier der Fehler klar wo anders. Etwa bei der Zeichencodierung - es ist verdächtig, wenn nach dem betreffenden Zeichen einfach "nix" mehr kommt.
Es ist ja noch gar nicht klar, ob das auf dem Hin- oder dem Rückweg verloren geht. Wie hat Amerlander denn festgestellt, dass der Text in der Datenbank nicht ankommt? Darüber lässt er uns doch im Dunkeln.
Und WO er htmlspecialchars() oder htmlentities() verwendet hat, hat er uns auch nicht wirklich erzählt.
Ich vermute, dass der Teil ab dem Spezialhäkchen erst bei der Interpretation im Browser verloren geht, also in der letzten Instanz des Rückweges.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
Es ist ja noch gar nicht klar, ob das auf dem Hin- oder dem Rückweg verloren geht. Wie hat Amerlander denn festgestellt, dass der Text in der Datenbank nicht ankommt? Darüber lässt er uns doch im Dunkeln.
Das lässt sich wunderbar nachvollziehen. Man nehme eine Verbindung zu einem MySQL-Server und stelle UTF-8 auf dieser ein. Dann sende man irgendwas, das kein UTF-8 ist, und MySQL schneidet an dieser Stelle den String ab. Das wird mit einer Warnung kommentiert, die man normalerweise nicht sieht. Warnungen muss unter PHP mit Statements abfragen, Funktionen dafür bietet nur die mysqli-Extension.
Dieses Fehlerbild hatte ich noch im Hinterkopf und es mal eben schnell zum Verifizieren nachgestellt. Ansonsten ist es natürlich immer von Vorteil für konkrete Antworten, wenn man das Problem so nachstellbar wie möglich darlegt.
Und WO er htmlspecialchars() oder htmlentities() verwendet hat, hat er uns auch nicht wirklich erzählt.
Wenn man weiß, dass es beim Eintragen passiert, ist dieses WO auch klar.
Ich vermute, dass der Teil ab dem Spezialhäkchen erst bei der Interpretation im Browser verloren geht, also in der letzten Instanz des Rückweges.
Nicht richtig vermutet.
dedlfix.
Hello,
Wenn man weiß, dass es beim Eintragen passiert, ist dieses WO auch klar.
Woher weiß man das, wenn man so vorgeht, wie Amerlander?
Ich vermute, dass der Teil ab dem Spezialhäkchen erst bei der Interpretation im Browser verloren geht, also in der letzten Instanz des Rückweges.
Nicht richtig vermutet.
Naja, dann warte ich eben noch ein bisschen länger auf meinen Wäschetrockner :-)
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
Wenn man weiß, dass es beim Eintragen passiert, ist dieses WO auch klar.
Woher weiß man das, wenn man so vorgeht, wie Amerlander?
Du meinst vermutlich wie man auf die Ursache des Problems kommen kann und nicht wo das htmlspecialchars() verwendet wird, worauf sich die WO-Aussage bezog. Nun, man könnte darauf kommen, indem man genau hinschaut. Und "genau" heißt bei einem Problem mit Strings/Zeichen bis "runter" zu deren Bytes. Dann könnte man erkennen, dass die Kodierung nicht stimmt. Natürlich braucht man dazu das Grundlagenwissen zu Zeichen und deren Darstellung im Computer.
Nicht richtig vermutet.
Naja, dann warte ich eben noch ein bisschen länger auf meinen Wäschetrockner :-)
Du könntest die Bildpunkte von überflüssigen Satzzeichen sammeln, davon liegen genügend in Foren und Blog-Kommentaren rum.
dedlfix.
Hello,
Wenn man weiß, dass es beim Eintragen passiert, ist dieses WO auch klar.
Woher weiß man das, wenn man so vorgeht, wie Amerlander?Du meinst vermutlich wie man auf die Ursache des Problems kommen kann und nicht wo das htmlspecialchars() verwendet wird, worauf sich die WO-Aussage bezog. Nun, man könnte darauf kommen, indem man genau hinschaut. Und "genau" heißt bei einem Problem mit Strings/Zeichen bis "runter" zu deren Bytes. Dann könnte man erkennen, dass die Kodierung nicht stimmt. Natürlich braucht man dazu das Grundlagenwissen zu Zeichen und deren Darstellung im Computer.
Genau. Ich meine, wenn man eine ganz normale Fehlerbehandlung betreibt, das Escaping stimmt, usw. Ich wäre jetzt nicht darauf gekommen, dass MySQL hier in den Datenstriom eingreift, nur weil die Codierung nicht stimmt. Wenn das Escaping passt, dürfte das die Datenbank doch eigentlich hier nicht interessieren - war mein Gedanke. Kannst Du mir erklären, mit welcher Berechtigung MySQL hier Daten verstümmelt (bitte bei ordnungsgemäßem Escaping!)?
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
Ich meine, wenn man eine ganz normale Fehlerbehandlung betreibt, das Escaping stimmt, usw. Ich wäre jetzt nicht darauf gekommen, dass MySQL hier in den Datenstriom eingreift, nur weil die Codierung nicht stimmt. Wenn das Escaping passt, dürfte das die Datenbank doch eigentlich hier nicht interessieren - war mein Gedanke. Kannst Du mir erklären, mit welcher Berechtigung MySQL hier Daten verstümmelt (bitte bei ordnungsgemäßem Escaping!)?
Was würdest du tun? Irgendeinen Tod musst du bei der Sache sterben. Fakt ist, Mysql bekommt ein fehlerhaft kodiertes Statement, und da kannst du nicht erwarten, dass es fehlerfrei damit arbeiten kann. Statt Abschneiden käme lediglich noch die Ersetzung durch das "replacement character" (U+FFFD, �) in Frage mit irgendeinem anschließendem Versuch, im nachfolgenden Bytestrom wieder was Sinnvolles zu erkennen. Und das kann unter Umständen gleich zu einer Sicherheitslücke führen. Wenn es einmal aus dem Tritt gekommen ist, helfen auch keine korrekten Escape-Sequenzen, denn dann könnte man auch mittenrein treten unter der Annahme, dass das \ noch zur UTF-8-Sequenz hätte gehören sollen. Die Anzahl der Folgebytes einer UTF-8-Sequenz geht ja aus deren erstem Byte hervor.
Welche Annahme soll MySQL denn in einer solchen Situation treffen? Als global verwendbares Tool kann es nicht einfach davon ausgehen, dass das Latin1 ist. Es kann ja auch eine verfälschte Datenübertragung gewesen sein, bei der nur zufällig ein paar Bits verändert wurden oder auch Bytes verschwunden sind. Und dann kommt noch die MySQL-Philosophie ins Spiel, dass diverse Dinge einfach nicht zu streng gehandhabt werden, was sicherlich auch ein Beitrag zum Erfolg MySQLs war.
Wie auch immer, es kann mit der Nicht-UTF-8-Kodierung einfach nicht weiterarbeiten, denn der nächste Schritt kann schon eine Umkodierung zum Zwecke der Stringverarbeitung oder in die Feldkodierung sein. Damit geht dann unter Umständen auch noch das Replacement Character verloren (wird vielleicht durch ein schnödes Fragezeichen ersetzt) und man kann gleich gar nicht mehr richtig erkennen, bei welchem Schritt nun der Verlust aufgetreten ist.
dedlfix.
Hello,
Ich meine, wenn man eine ganz normale Fehlerbehandlung betreibt, das Escaping stimmt, usw. Ich wäre jetzt nicht darauf gekommen, dass MySQL hier in den Datenstriom eingreift, nur weil die Codierung nicht stimmt. Wenn das Escaping passt, dürfte das die Datenbank doch eigentlich hier nicht interessieren - war mein Gedanke. Kannst Du mir erklären, mit welcher Berechtigung MySQL hier Daten verstümmelt (bitte bei ordnungsgemäßem Escaping!)?
Was würdest du tun? Irgendeinen Tod musst du bei der Sache sterben. Fakt ist, Mysql bekommt ein fehlerhaft kodiertes Statement, und da kannst du nicht erwarten, dass es fehlerfrei damit arbeiten kann. Statt Abschneiden käme lediglich noch die Ersetzung durch das "replacement character" (U+FFFD, �) in Frage mit irgendeinem anschließendem Versuch, im nachfolgenden Bytestrom wieder was Sinnvolles zu erkennen. Und das kann unter Umständen gleich zu einer Sicherheitslücke führen. Wenn es einmal aus dem Tritt gekommen ist, helfen auch keine korrekten Escape-Sequenzen, denn dann könnte man auch mittenrein treten unter der Annahme, dass das \ noch zur UTF-8-Sequenz hätte gehören sollen. Die Anzahl der Folgebytes einer UTF-8-Sequenz geht ja aus deren erstem Byte hervor.
Das Escapezeichen \ kommt doch im internen Datenpuffer gar nicht an. Es wird doch bereits von der Textschnittstelle ersetzt, die Befehlscode und Daten wieder voneinander trennt.
Es MUSS der Datenbanksoftware mMn egal sein, was in den Daten drinsteht.
Wenn ich in einem Textfeld ein Bild speichern will, dann darf MySQL das nicht verhindern.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
Das Escapezeichen \ kommt doch im internen Datenpuffer gar nicht an. Es wird doch bereits von der Textschnittstelle ersetzt, die Befehlscode und Daten wieder voneinander trennt.
Das funktioniert bei UTF-8. Es gibt aber asiatische Kodierungen, da musst du zuerst die Bedeutung aus dem Datenstrom lesen, bevor du zwischen \ und dessen Byte als Bestandteil eines anderen Zeichens unterscheiden kannst. Nicht umsonst arbeitet mysql_real_escape_string() kodierungsabhängig, was nur für UTF-8 und Latin1 (und einige andere) unbeachtet gelassen werden kann.
Wenn du als Programmierer solche uneindeutigen Kodierungen beachten müsstest, würdest du vermutlich auch erst die Zeichendekodierung und dann erst die Demaskierung vornehmen. Und das generell, nicht mal so und mal so.
Es MUSS der Datenbanksoftware mMn egal sein, was in den Daten drinsteht.
Nö. Ein Computer kennt den Zustand 'egal' nicht. Der braucht klare Verhältnisse für alle Lebenslagen. Wenn wir es mit im Statement eingebundenen Daten zu tun haben, kann die Kodierung nicht egal sein, denn sonst kann das Statement nicht richtig interpretiert werden. Bei Prepared Statements und den damit einhergehenden separaten Wegen für Statement und Daten ist das zunächst was anderes. Doch für die Weiterverarbeitung wird es dann wieder interessant, wenn MySQL die Zeichen erkennen muss, um korrekte Stringverarbeitung hinzubekommen.
Wenn ich in einem Textfeld ein Bild speichern will, dann darf MySQL das nicht verhindern.
Das Feld spielt an dieser Stelle noch gar keine Rolle. Wir sind beim Lesen und Interpretieren des Bytestroms. Du brauchst auf alle Fälle eine Unterscheidung, zwischen den Fällen, wo MySQL die Zeichen interpretieren muss und wo nicht. Wenn du die Bilddaten im Statement mitschicken willst, hast du sowieso erstmal das Problem zu lösen, wie du die Daten dort derart reinbekommst, dass nicht irgendwelche Zeichen darin als Statementbestandteil oder gar String-Ende aufgefasst werden. Die Daten müssen also auf der einen Seite "vertextet" und auf der anderen Seite wieder zu in Benärdaten konvertiert werden können.
Zurück zum Feld, hier muss MySQL auch unterscheiden können, ob es dafür Stringverarbeitung braucht oder nicht. Du kannst natürlich Binärdaten jenseits von BLOBs unterbringen, solltest das aber nicht ohne 'bin' als Kodierungsangabe machen.
Wenn du den Zustand "egal" haben möchtest, musst du eine MySQL-Version vor 4.1 nehmen. Die hatten das Multi-Byte-"Problem" nicht (und auch keine Möglichkeit der Unicode-Stringverarbeitung). Textschnittstelle vs. Binärdaten musste aber auch damals schon beachtet werden.
dedlfix.
Moin Moin!
Ich meine, wenn man eine ganz normale Fehlerbehandlung betreibt, das Escaping stimmt, usw. Ich wäre jetzt nicht darauf gekommen, dass MySQL hier in den Datenstriom eingreift, nur weil die Codierung nicht stimmt.
Was mich an der Geschichte stört, ist, das MySQL offenbar (mal wieder) versucht, Dinge automatisch gerade zu biegen und dabei irgendeine Warnung ins Nirwana nuschelt statt sauber und laut mit einem Fehler abzubrechen.
Es MUSS der Datenbanksoftware mMn egal sein, was in den Daten drinsteht.
Nicht, wenn Du sagst, dass Du Text speichern willst. Text ist nur ein Subset aller möglichen Byte-Kombinationen. Angefangen damit, dass nicht jede beliebige Kombination von beliebigen Bytes ein gültiges Zeichen darstellt.
Wenn ich in einem Textfeld ein Bild speichern will, dann darf MySQL das nicht verhindern.
Bei binären Bild-Formaten durchaus. Wenn Du das Bild als Text darstellen kannst (z.B. XPM), darfst Du es auch in einer als Text (d.h. char, varchar, text) deklarierten Spalte speichern.
Alexander
Hi,
Was würdest du tun? Irgendeinen Tod musst du bei der Sache sterben. Fakt ist, Mysql bekommt ein fehlerhaft kodiertes Statement, und da kannst du nicht erwarten, dass es fehlerfrei damit arbeiten kann. Statt Abschneiden käme lediglich noch die Ersetzung durch das "replacement character" (U+FFFD, �) in Frage
Nein. Es gibt noch einen anderen Weg:
Das DBMS könnte das Statement auch als fehlerhaft zurückgewiesen werden, wenn Daten in einer anderen Codierung daherkommen als vereinbart.
cu,
Andreas
Tach!
Wenn in einem der Einträge aber ein richtiges Anführungszeichen (nur Englisch oder Deutsch, die Französischen gehen) vorkommt, dann bricht MySQL den Eintrag ab.
Aus
"Das ist ein „Beispieltext“"
Wird in die Datenbank dann nur das eingetragen:
"Das ist ein "
Schau dir MySQLs Warnungen an. SHOW WARNINGS ausführen und das Ergebnis fetchen und anzeigen. Dann wirst du vermutlich eine mit dem Wortlaut
Incorrect string value: '\x84Beisp...' for column 'text' at row 1
sehen. Das ist ein Zeichenkodierungsproblem. MySQL erwartet UTF-8, du sendest aber keins. Löse dieses Problem, indem du die beiden Grundsätze verstehst und entsprechende Vorkehrungen triffst:
Verwende durchgängig UTF-8 und mach dir klar, wer alles mit wem spricht in deiner Verarbeitungskette. Alles weitere findest du im Themenschwerpunkt Zeichenkodierung.
Ich verwende HTML htmlentities() und habe es auch schon mit
$text = str_replace("„","„",$text);
versucht.
Das ist eine Anwendung zum falschen Zeitpunkt und eine unnötige noch dazu. (siehe im bereits verlinkten Kontextwechsel-Artikel den Abschnitt HTML in der Datenbank)
Das bringt leider nichts, da das Zeichen einfach nicht ersetzt wird. Wenn ich dort die Zeichen austausche (beispielsweise "a" durch "b" ersetze) klappt es.
Auch hier hast du wieder ein Zeichenkodierungsproblem. Schau dir an, was ankommt und was du zu ersetzen versuchst. Dazu kannst du die Funktion urlencode() sehr gut <del>missbrauchen</del><ins>verwenden</ins>.
var_dump(urlencode("„"));
var_dump(urlencode($text));
Das „ wird unterschiedlich kodiert sein, weswegen PHP keine Übereinstimmung findet. Das heißt, deine PHP-Code-Datei ist nicht UTF-8-kodiert oder deine Daten sind es nicht.
dedlfix.
hi,
Die Seite auf welcher das Formular ist ist in Utf-8.
Im Fall „ kriegst Du die Oktetten E2 80 9E, das sind 3 Bytes für ein Zeichen. Guck ins PHP-Handbuch zum Thema mb_funktionen, die Mehrbytekodierungen verarbeiten können.
Hotti
Tach!
Die Seite auf welcher das Formular ist ist in Utf-8.
Im Fall „ kriegst Du die Oktetten E2 80 9E, das sind 3 Bytes für ein Zeichen. Guck ins PHP-Handbuch zum Thema mb_funktionen, die Mehrbytekodierungen verarbeiten können.
Das ist für den gezeigten Fall nicht notwendig, weil zum einen die Stringersetzungsfunktion überhaupt nicht benötigt wird, wenn man es richtig macht und zum anderen bei korrekter UTF-8-Kodierung der Nadel und des Heuhaufens die Verwendung der Byte-Funktionen zumindest beim Stringersetzen keine Probleme bereitet.
dedlfix.
hi,
Das ist für den gezeigten Fall nicht notwendig, weil zum einen die Stringersetzungsfunktion überhaupt nicht benötigt wird, wenn man es richtig macht und zum anderen bei korrekter UTF-8-Kodierung der Nadel und des Heuhaufens die Verwendung der Byte-Funktionen zumindest beim Stringersetzen keine Probleme bereitet.
Ja, freilich doch, definiere "richtig". Du bekommst utf-8-gefällige Bytes und stehst nun vor der Entscheidung, was Du in Richtung DB schicken sollst:
Schreib doch einfach mal auf, wie Du das mit PHP machst in beiden Fällen, das dürfte den OP interessieren.
Hotti
Tach!
Das ist für den gezeigten Fall nicht notwendig, weil zum einen die Stringersetzungsfunktion überhaupt nicht benötigt wird, wenn man es richtig macht und zum anderen bei korrekter UTF-8-Kodierung der Nadel und des Heuhaufens die Verwendung der Byte-Funktionen zumindest beim Stringersetzen keine Probleme bereitet.
Ja, freilich doch, definiere "richtig".
Hab ich gemacht. Siehe die beiden Grundsätze. Wenn alle Zeichenkodierungsangaben korrekt deklariert sind, gibt es normalerweise keine Unstimmigkeiten zwischen den Beteiligten. Es sei denn, jemand macht mutwillig was anderes, dann ist es im Allgemeinen egal, weil diese Daten dann sicherlich nicht im Kontext der Anwendung sinnvoll sind. Zu dem kämen noch Fehlkonfigurationen von Browsern aufgrund von Unwissen, doch die sind eher selten. Man könnte noch mit gutem Willen auf korrekte UTF-8-Kodierung prüfen und ansonsten Latin1 annehmen und umkodieren, aber diese Annahme und Korrekturmaßnahme passt grad mal auf große Teile des westlichen Kulturkreises und ist für den Rest auch fehlerhaft. Alles andere wird verhältnismäßig aufwendig und unwirtschaftlich.
Du bekommst utf-8-gefällige Bytes und stehst nun vor der Entscheidung, was Du in Richtung DB schicken sollst:
- Bytes
oder- Zeichenketten
Diese Entscheidung muss ich für den vorliegenden Fall unter derzeitigem PHP nicht treffen.
Schreib doch einfach mal auf, wie Du das mit PHP machst in beiden Fällen, das dürfte den OP interessieren.
Unter der Annahme, dass UTF-8-kodierte Daten mit dem Request reinkommen, müssen diese einfach nur durchgereicht werden. PHP nimmt die Bytes und Byte-Sequenzen der Zeichen und schiebt sie 1:1 an das DBMS weiter, solange man nichts an ihnen ändert (Kontextbehandlung darf man machen, die ist für UTF-8-Byte-Sequenzen (also Zeichen jenseits von ASCII) ungefährlich).
dedlfix.
Moin,
Unter der Annahme, dass UTF-8-kodierte Daten mit dem Request reinkommen, müssen diese einfach nur durchgereicht werden. PHP nimmt die Bytes und Byte-Sequenzen der Zeichen und schiebt sie 1:1 an das DBMS weiter, solange man nichts an ihnen ändert (Kontextbehandlung darf man machen, die ist für UTF-8-Byte-Sequenzen (also Zeichen jenseits von ASCII) ungefährlich).
Interessant. Das ist, wenn ich das mal mit der Entwicklung von Perl vergleiche, der Stand von 2004 ;)
Hotti
Tach!
Unter der Annahme, dass UTF-8-kodierte Daten mit dem Request reinkommen, müssen diese einfach nur durchgereicht werden. PHP nimmt die Bytes und Byte-Sequenzen der Zeichen und schiebt sie 1:1 an das DBMS weiter, solange man nichts an ihnen ändert (Kontextbehandlung darf man machen, die ist für UTF-8-Byte-Sequenzen (also Zeichen jenseits von ASCII) ungefährlich).
Interessant. Das ist, wenn ich das mal mit der Entwicklung von Perl vergleiche, der Stand von 2004 ;)
Es ist kein Geheimnis, und auch nicht zum ersten Mal hier erwähnt worden, dass PHP immer noch von der Annahme 1 Zeichen = 1 Byte ausgeht. Änderungen sind erst mit der nächsten Major-Version angekündigt. Die Entwicklung dazu zieht sich, warum auch immer, seit 2005 hin. Für die meisten Aufgabenstellungen ist das meiner Meinung nach jedoch ausreichend, denn da hat PHP mehr oder weniger nur eine Durchreichfunktion zwischen Webserver und Datenhaltung. Und wenn wirklich mal Multibyte-String-Verarbeitung nötig ist, gibt es ja diverse Funktionen dafür.
dedlfix.
Hello,
Es ist kein Geheimnis, und auch nicht zum ersten Mal hier erwähnt worden, dass PHP immer noch von der Annahme 1 Zeichen = 1 Byte ausgeht. Änderungen sind erst mit der nächsten Major-Version angekündigt.
Ich frage mich sowieso immer, worin das Geheimnis des Zusammenwachsens der Welt liegt. Wenn man sich auf 127 Zeichen für die schriftliche Darstellung beschränken würde, oder wenn man den Zeichenvorrat aufbläst bis zum Sankt Nimmerleinstag.
Ich bin immer noch der Meinung, dass UTF-8 der falsche Weg ist. Hier ist der Liberalismus übertreiebn und fehl am Platze. OK, wir Deutschen müssten nur auf vier sieben Zeichen verzichten ä, ö, ü, Ä, Ö, Ü und ß. Das würden wir relativ schnell und wenig sinnverfelschend (sic!) hinbekommen.
Bei den Verwendern anderer Schriftzeichen hat sich ohnehin meistens schon eine Parallelerziehung durchgesetzt. Sie lernen also schon seit ca. 20-30 Jahren auch die lateinische Schreibweise, zumindest, wenn sie Englisch oder Französisch lernen.
In China setzt sich das auch langsam durch und junge Chinesen schreiben teilweise lieber in lateinischer Schrift, als in eigenen Schriftzeichen.
Warum sollen wir nun also alle Millionen anderer Schriftzeichen lernen und dann auch noch die recht komplizierte Darstellung auf Byteebene verstehen und umsetzen lernen (in beiden Richtungen). Das ist Babylon!
In der Reduzierung liegt hier der mMn bessere Weg.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
Ich frage mich sowieso immer, worin das Geheimnis des Zusammenwachsens der Welt liegt. Wenn man sich auf 127 Zeichen für die schriftliche Darstellung beschränken würde, oder wenn man den Zeichenvorrat aufbläst bis zum Sankt Nimmerleinstag.
Die Chancen, sich auf 127 Zeichen beschränken zu können, sind entweder vor einigen Jahrtausenden oder vor einigen Jahrzehnten verspielt worden. Die erste Grenze wurde durch die Entwicklung der anderen Sprach- und Schriftsysteme überschritten, bei denen es schwer ist, eine Romanisierung und noch dazu mit Beschränkung auf ASCII hinzubekommen. Die andere Grenze war der eiserne Vorhang - und man hätte mindestens Griechenland mit seinen komischen Zeichen hinter selbigen abschieben müssen. Und warum brauchst du 127 Zeichen? Wozu getrennte Groß- und Kleinbuchstaben?
Ich bin immer noch der Meinung, dass UTF-8 der falsche Weg ist. Hier ist der Liberalismus übertreiebn und fehl am Platze. OK, wir Deutschen müssten nur auf vier sieben Zeichen verzichten ä, ö, ü, Ä, Ö, Ü und ß. Das würden wir relativ schnell und wenig sinnverfelschend (sic!) hinbekommen.
Bei den Verwendern anderer Schriftzeichen hat sich ohnehin meistens schon eine Parallelerziehung durchgesetzt. Sie lernen also schon seit ca. 20-30 Jahren auch die lateinische Schreibweise, zumindest, wenn sie Englisch oder Französisch lernen.
In China setzt sich das auch langsam durch und junge Chinesen schreiben teilweise lieber in lateinischer Schrift, als in eigenen Schriftzeichen.
Das funktioniert mit ASCII nicht. Mandarin-Chinesisch hat 4 Töne, die bedeutungsunterscheidend sind. Hinzu kommt, dass es viel weniger Silben gibt (ca. 400, mit Tönen 1300 - im Deutschen über 10.000), die Unterscheidungsmöglichkeiten zwischen Wörtern/Silben schon dadurch ziemlich eingeschränkt sind. Mit Pinyin, einer Romanisierungsform, muss man diese vier Töne kennzeichnen, damit man sie überhaupt auseinanderhalten und den Sinn nicht nur aus dem Kontext ermitteln kann und schon hast du neben aeiou und ü! auch noch ǎěǐǒǔǚ, āēīōūǖ, àèìòùǜ, áéíóúǘ, also schonmal 24 weitere Zeichen. Andere chinesische Sprachen haben zum Beispiel 9 Töne. Die Vietnamesen haben sich für lateinische Buchstaben entschieden. Hast du dir mal deren Diakritika-Wald angesehen (12 Vokale × 6 Töne + 1 Zeichen = 73 Zeichen)?
Warum sollen wir nun also alle Millionen anderer Schriftzeichen lernen und dann auch noch die recht komplizierte Darstellung auf Byteebene verstehen und umsetzen lernen (in beiden Richtungen). Das ist Babylon!
Unsinn. Zeichenlernzwang besteht keiner. Das bringt auch nichts, wenn du die damit üblicherweise verschriftlichten Sprachen nicht verstehst.
Die Abschaffung der anderen Schriftsysteme ist nicht sinnvoll möglich. Das Babylon der verschiedenen nationalen Zeichensätze und -kodierungen ist noch unerträglicher.
In der Reduzierung liegt hier der mMn bessere Weg.
Nur, wenn du Englisch als Weltsprache unter Abschaffung aller anderen Sprachen durchsetzen kannst.
dedlfix.
Hello,
Nur, wenn du Englisch als Weltsprache unter Abschaffung aller anderen Sprachen durchsetzen kannst.
Das ist allerdings genauso gescheitert bisher, wie die Versuche von Kaiser Wilhelm bis A. H., Deutsch durchzusetzen.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach,
Warum sollen wir nun also alle Millionen anderer Schriftzeichen lernen und dann auch noch die recht komplizierte Darstellung auf Byteebene verstehen und umsetzen lernen (in beiden Richtungen). Das ist Babylon!
Ich sehe nicht, warum du Millionen von Schriftzeichen lernen mußt und >99% der Menschen können UTF-8, u.ä. einfach benutzen ohne dass sie sich Gedanken um Bytes machen.
Warum sollte eine (große) Mehrheit der Menschheit sich unserer westlichen Schriftsprache (und ich meine schon hier brauchen wir pro Sprache ein eigenes Alphabet) unterwerfen, das ist Kulturimperialismus!
In der Reduzierung liegt hier der mMn bessere Weg.
Das passiert automatisch mit der Zeit, Sprache ist im Laufe der Zeit immer eher einfacher als komplizierter geworden (von seltenen Ausnahmen abgesehen).
mfg
Woodfighter
Tach!
Sprache ist im Laufe der Zeit immer eher einfacher als komplizierter geworden (von seltenen Ausnahmen abgesehen).
Wobei das Zitat nur ein "ganz normales" Futur II ist. Dazu braucht es keine Zeitreisen, man muss nur mal von einer abgeschlossenen Handlung in der Zukunft ausgehen: Nächste Woche werde ich meinen Urlaub beendet haben.
dedlfix.
Tach,
Sprache ist im Laufe der Zeit immer eher einfacher als komplizierter geworden (von seltenen Ausnahmen abgesehen).
Wobei das Zitat nur ein "ganz normales" Futur II ist. Dazu braucht es keine Zeitreisen, man muss nur mal von einer abgeschlossenen Handlung in der Zukunft ausgehen: Nächste Woche werde ich meinen Urlaub beendet haben.
richtig, aber Futur II ist für die meisten ja schon ein ungenutztes und kompliziertes grammatisches Konstrukt. Ich möchte aber nebenher noch festhalten, dass das Zitat ursprünglich natürlich nicht von mir stammt.
mfg
Woodfighter
Hello,
[...] (Kontextbehandlung darf man machen, die ist für UTF-8-Byte-Sequenzen (also Zeichen jenseits von ASCII) ungefährlich).
Das bezieht sich auch nur auf die SQL-Textschnittstelle. Und da liegen alle Steuerzeichen unterhalb #128. Das betrifft also sowieso nur einbytige UTF-8-Sequenzen. Das Escapezeichen selber ist ebenfalls aus dem Raum unterhalb #128.
Deshalb kann ich auch nicht verstehen, wenn MySQL dann in den anderen Bytes herumfummelt und den Datenstrom abschneidet. Ich kann es sogar immer noch nicht glauben.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
[...] (Kontextbehandlung darf man machen, die ist für UTF-8-Byte-Sequenzen (also Zeichen jenseits von ASCII) ungefährlich).
Deshalb kann ich auch nicht verstehen, wenn MySQL dann in den anderen Bytes herumfummelt und den Datenstrom abschneidet. Ich kann es sogar immer noch nicht glauben.
Siehe: https://forum.selfhtml.org/?t=208569&m=1418614
dedlfix.
Vielen Dank für die vielen Tipps und die anregende Diskussion.
Das hat mich dazu bewegt mich etwas tiefer mit der Materie zu beschäftigen.
Der Fehler war aber insgesamt recht simpel:
in der .htacces wurde eine Headder-Information an den Browser geschickt mit dem Charset iso-8859-1. Dadurch wurde mein Charset ignoriert.
Erst hab ich das Formular auf "accept-charset="UTF-8" gestellt, dann ging schon mal alles bis zur MySQL Tabelle gut und erst beim auslesen traten wieder Fehler auf. (Gleiches auch als ich davor noch "utf8_encode()" ausprobierte.
Nunja, die eigentliche Lösung war dann aber logischerweise einfach die .htacces Datei dementsprechend zu ändern.
Jetzt klappt alles wunderbar! :)
Gruß
Amerlander
Tach!
in der .htacces wurde eine Headder-Information an den Browser geschickt mit dem Charset iso-8859-1. Dadurch wurde mein Charset ignoriert.
Erst hab ich das Formular auf "accept-charset="UTF-8" gestellt, dann ging schon mal alles bis zur MySQL Tabelle gut und erst beim auslesen traten wieder Fehler auf.
Mit der falschen HTTP-Header-Angabe ist das kein Problem vom Auslesen (vorausgesetzt, das DBMS-Handling ist soweit in Ordnung, also mit korrekt ausgehandelter Verbindungskodierung). Das könntest du feststellen, wenn du dir die Daten ansiehst, die direkt aus dem DBMS kommen. Deren Bytewerte müssten den entsprechenden UTF-8-Sequenzen der jeweiligen Zeichen entsprechen. Durch das ISO-8859-1 in Richtung Browser interpretiert dieser jedoch das UTF-8 nicht richtig. Also ist das ein Problem beim Anzeigen.
Das accept-charset im Form-Element kann man nehmen, muss man aber letzlich nicht. Zumindest einige ältere Browser ignorieren diese Angabe und wenn man sich darauf verlässt, hat man verloren. Es klappt aber üblicherweise immer, dass die Browser die Kodierungsangabe der Seite für die Kodierung der Formulardaten heranziehen.
(Gleiches auch als ich davor noch "utf8_encode()" ausprobierte.
Wenn du noch solche und ähnliche Konvertierungen (außer der Kontextwechselbehandlung) zu benötigen glaubst, hast du noch Baustellen offen auf dem Weg hin zu vollständiger UTF-8-Verarbeitung.
dedlfix.
Tach!
in der .htacces wurde eine Headder-Information an den Browser geschickt mit dem Charset iso-8859-1. Dadurch wurde mein Charset ignoriert.
Erst hab ich das Formular auf "accept-charset="UTF-8" gestellt, dann ging schon mal alles bis zur MySQL Tabelle gut und erst beim auslesen traten wieder Fehler auf.Mit der falschen HTTP-Header-Angabe ist das kein Problem vom Auslesen (vorausgesetzt, das DBMS-Handling ist soweit in Ordnung, also mit korrekt ausgehandelter Verbindungskodierung). Das könntest du feststellen, wenn du dir die Daten ansiehst, die direkt aus dem DBMS kommen. Deren Bytewerte müssten den entsprechenden UTF-8-Sequenzen der jeweiligen Zeichen entsprechen. Durch das ISO-8859-1 in Richtung Browser interpretiert dieser jedoch das UTF-8 nicht richtig. Also ist das ein Problem beim Anzeigen.
Das accept-charset im Form-Element kann man nehmen, muss man aber letzlich nicht. Zumindest einige ältere Browser ignorieren diese Angabe und wenn man sich darauf verlässt, hat man verloren. Es klappt aber üblicherweise immer, dass die Browser die Kodierungsangabe der Seite für die Kodierung der Formulardaten heranziehen.
(Gleiches auch als ich davor noch "utf8_encode()" ausprobierte.
Wenn du noch solche und ähnliche Konvertierungen (außer der Kontextwechselbehandlung) zu benötigen glaubst, hast du noch Baustellen offen auf dem Weg hin zu vollständiger UTF-8-Verarbeitung.
Diese Baustellen waren ja nur um zu sehen wo das Problem steckt.
Mit "Accept Charset" habe ich dafür gesorgt, das er das Formular in utf-8 sendet und nicht in ISO-8859-1, da er bei falschem Headder ja auch das falsche formular charset sendet. Das war dann anfangs auch der grund weshalb er es nicht in der DB speichern konnte. Mit dem utf8_encode habe ich das selbe gemacht - aber eben auch nur zu testzwecken.
Wenn ich nicht weiß wo der Fehler sitzt probiere ich einfach viel aus um die stelle zu finden wo es hakt.
Jetzt verwende ich das natürlich nicht mehr, ich kann die Daten einfach so speichern ohne hin und her zu codieren. Nur html entieties verwende ich noch (es sollte doch eigentlich egal sein, ob ich die funktion vor dem speichern oder beim auslesen verwende? Aber so kann ich sie in der Speicherfunktion verwenden und muss sie nicht auf verschiedenen Seiten jeweils extra beim auslesen angeben und brauche mir keine sorgen zu machen sie mal zu vergessen und dann von einem Witzbold ein </div> oder so in mein HTML zu bekommen.)
Und mysql_real_escape_string() verwende ich jetzt vor dem speichern nun auch noch, vielen dank, dass ihr mich auf die Funktion aufmerksam gemacht habt. Ich arbeite eben noch nicht sehr lange mit php.
gruß
Amerlander
Tach!
Mit "Accept Charset" habe ich dafür gesorgt, das er das Formular in utf-8 sendet und nicht in ISO-8859-1, da er bei falschem Headder ja auch das falsche formular charset sendet.
"Er" ist in diesem Fall nur der Browser, den du grade verwendest. Andere ignorieren das accept_charset möglicherweise.
Wenn ich nicht weiß wo der Fehler sitzt probiere ich einfach viel aus um die stelle zu finden wo es hakt.
Das Probieren allein ist ungünstig. Damit findet man nur zufällig eine gängige Konstellation, weiß aber nicht genau, ob man das Problem nun ganz gelöst hat oder nur teilweise. Genau nachschauen ist immer besser. Was für Bytes schickt denn der Browser da? Ist es die Kodierung, die ich von ihm erwarte? Solche Fragen musst du bei einer Fehlersituation zu klären versuchen.
Nur html entieties verwende ich noch (es sollte doch eigentlich egal sein, ob ich die funktion vor dem speichern oder beim auslesen verwende?
htmlentities() ist unsinnig. Du verwendest doch UTF-8, kannst damit alle Zeichen direkt ausgeben und musst keine Ersatzschreibweise verwenden. Lediglich die HTML-eigenen Zeichen müssen berücksichtigt werden und das macht htmlspecialchars().
Wo man das anwendet, ist alles andere als egal. Siehe Kontextwechsel - HTML in der Datenbank.
Aber so kann ich sie in der Speicherfunktion verwenden und muss sie nicht auf verschiedenen Seiten jeweils extra beim auslesen angeben und brauche mir keine sorgen zu machen sie mal zu vergessen und dann von einem Witzbold ein </div> oder so in mein HTML zu bekommen.)
Die Ersparnis trügt. Du must jetzt nur noch mehr auspassen, welche Daten schon behandelt sind und welche nicht. Stringverarbeitung ist mit behandelten Daten auch nicht ohne weiteres möglich (siehe Link).
Und mysql_real_escape_string() verwende ich jetzt vor dem speichern nun auch noch, vielen dank, dass ihr mich auf die Funktion aufmerksam gemacht habt. Ich arbeite eben noch nicht sehr lange mit php.
Den Kontextwechsel muss man in jedem System beachten, nicht nur in PHP.
dedlfix.