PHP Umlaute und MySQL (wieder einmal)

  • Ersteller Ersteller + BELA B. +
  • Erstellt am Erstellt am
carom schrieb:
Liege ich falsch, oder ist die Multibytestring-Erweiterung pflicht?
Ich nutze die ganzen mb_* Funktionen persönlich gar nicht. Wenn wirklich alles in UTF-8 gespeichert und transportiert wird, hast du auch mit asiatischen oder exostischen Zeichen (ฬᣫ⧭⌨ᚏഈ㒀㐤䓲⣑⢟Ϡ☯❿❖ଇ) keinerlei Probleme und musst nichts konvertieren oder sonstigen Hickhack anwenden.

Die Frage dabei ist natürlich immer, wie und wo man etwas verwendet. Ich persönlich weiß gar nicht mehr, wann ich das letzte Mal strlen irgendwo benutzt habe. Wenn kommen Sachen so in die DB, wie sie ankommen und auch so raus. Um die Begrenzungen kümmert sich der Browser (<input size="">), sowie die DB selbst. Wenn der User die Beschränkung im HTML selbst entfernt, hat er eben das Problem an der Backe und die DB schneidet alles überflüssige dann halt weg. Das Escaping ist durch Prepared Statements gesichert. strlen im Code ist ja so weit wie möglich eh auf ASCII begrenzt, von daher kann es dort nicht zu Problemen kommen. Aber da sollte man sowieso auf Konstanten und (in PHP nicht vorhandene) Enumerations ausweichen und nicht irgendwelche beliebigen Strings übergeben.

Die Aussage bezieht sich hier nur aufs Encoding-Problem, da wie du ja selbst siehst, die beiden Zeichen zu keinem ö werden, trotz der Funktionen. Aber wie gesagt: Solche Probleme sind bei mir noch nie aufgetreten (außer bei UTF-8 Umstellungen), ergo kümmer ich mich erst dann darum, wenn so ein Fall wirklich auftritt.

edit: Und bumms, war das Forum zu blöd für utf8 und hat alles abgeschnitten... -.-
 
ice-breaker schrieb:
Ja man braucht die mbstring-Bibliothek

Gut zu wissen :)

@Yuuri:

Klar, was als UTF-8 reinkommt muss man nicht Konvertieren. Ich fände jegliche Konvertierungen eh unschön.

Aber es geht ja um Operationen auf Zeichenketten. Du meinst, du setzt selten welche ein, aber das ist mir eher ein Rätsel wie du das machst. Zeichenbeschränkungen in HTML sind maximal als Hilfe für den Benutzer gedacht, und das ganze auf die DB auszulagern und diese somit als einzige konsistenzsichernde Maßnahme einzusetzen ist meiner Ansicht nach gar kein guter Stil. Dass es funktioniert steht außer Frage, aber das ist ja nicht alles.
 
Am Ende sagt uns das alles aber nur wieder eines: Verwende von ANFANG AN vernünftige Abstraktionen.

Kann man das Projekt in einem CMS lösen? Nimm ein CMS.
Wären zu viele Modifikationen am CMS nötig? Nimm ein Framework.
Sind zu viele Modifikationen am Framework nötig? Du hast was falsch gemacht!

Jedes halbwegs brauchbare Framework arbeitet durch die Bank weg mit sauberen UTF-8 - Verbindungen. Wenn man also seinen Kram von 0 an richtig schreibt hat man niemals solche dusseligen Encoding-Sorgen.

@carom:
1.) Konsistenzsicherung ist genau DER Zaubertrick, den ACID-konforme Datenbanken eben perfekt beherrschen. Genau da gehört Konsistenzsicherung hin, nicht in die Programmlogik.
2.) Wenn du es doch in der Programmlogik haben willst, schreib dir ne vernünftige Abstraktion. Keinesfalls solltest du 50x den selben mb_... - Kram schreiben.
 
Zuletzt bearbeitet:
Daaron schrieb:
@carom
1.) Konsistenzsicherung ist genau DER Zaubertrick, den ACID-konforme Datenbanken eben perfekt beherrschen

Habe ich nie bezweifelt :)

Daaron schrieb:
Genau da gehört Konsistenzsicherung hin, nicht in die Programmlogik.

Da kann ich dir überhaupt nicht zustimmen (natürlich sollte eine DB ihre Konsistenz nach Möglichkeit absichern, aber das meine ich nicht). Nochmal zur Verdeutlichung: es geht mir um die Vorgehensweise, die Datenbank als einzige, ausschließliche Maßnahme einzusetzen. Klar sollte man ansonsten die Möglichkeiten nutzen, die einem die DB gibt. Vielleicht haben wir aber auch nur unterschiedliche Vorstellungen vom Begriff "konsistenzsichernde Maßnahme", die fängt bei mir jedenfalls schon bei der Validierung des Userinputs an.

Warum willst du Dinge, die ein Webserver machen könnte, jedes mal die Datenbank durchschleifen? Webserver sind billig und skalieren prächtig, Datenbankserver zu skalieren ist kann je nach Szenario schon schwierig genug sein, wenn man sie nur als "Datenablage" ansieht. Für jede Falscheinagbe des Benutzers musst du den DB-Server völlig unnötig erneut bemühen, statt das alles schon eine Position weiter vorne abzufrühstücken. Im Idealfall geht jede "Conversion" (Registrierung, Newsletteranmeldung etc.) genau ein mal auf die DB und nicht 5-10 mal bei unzulässigem Aufbau des Namens oder Email. Das wird keine der größeren Plattformen im Web so machen.

Was ist mit der Austauschbarkeit der Datenbank? Ein Framework zur Abstraktion einzusetzen und dann doch DB-spezifisch Dinge regeln?

Wenn ich keine Lust _hätte_, die Integrität der Daten zwei mal zu Prüfen (Programmcode + DB), dann würde ich die Prüfung im Programmcode ehrlich gesagt vorziehen und nur die kritischen Sachen in der DB zur Absicherung. Bei einem eventuellen Code-First Ansatz möchte ich mich eigentlich gar nicht mehr so sehr um die DB kümmern müssen, Tuning ausgenommen.

Und klar kann man einen Großteil der Last schon auf Clientseite im Keim ersticken. Aber es ist eben nicht ausreichend, und nicht alle Anwendungen haben überhaupt ein Nutzer-Frontend mit JS dran, z.B. wenn man APIs oder Services anbietet, die beliebig konsumiert werden können.

2.) Wenn du es doch in der Programmlogik haben willst, schreib dir ne vernünftige Abstraktion. Keinesfalls solltest du 50x den selben mb_... - Kram schreiben.

Viele Frameworks haben das ja bereits fertig zur Hand, wobei ich mich mit PHP-Frameworks nicht auskenne.
 
Zuletzt bearbeitet:
Input-Validierung ist so oder so fällig, gerade im Hinblick auf Pflichtfelder, Gleichheit bei neuen Passwörtern,...

Aber muss man da wirklich auch noch auf Länge prüfen in der Programmlogik? Das ist doch Overhead ohne Ende.
1. Prüfung: HTML-Code. Gerade HTML5 bietet hier verdammt viel
2. Prüfung: evtl. n JS-basierter Validator, gerade als Fallback für HTML5
3. Prüfung: Datenbank verwirft Überhang kommentarlos

Hier noch einen Schritt dazwischen zu packen, nur weil einige Idioten unbedingt gefälschte POSTs schicken, ist doch Zeitverschwendung.
 
Ich kanns leider nicht mehr exakt zurückverfolgen aber hatte einen Fall in dem ein &nbsp; ( und andere Zeichen ) eine Funktion zerschossen hat. Beispiel Forum. Post 1 hat ein &nbsp; und wird genullt, dazu werden alle weiteren Posts genullt. Ob ein preq_replace, htmlentities oder was auch immer Schuld waren weiß ich nicht mehr.

Bei mir ist mittlerweile eigentlich alles auf UTF-8 eingestellt, auch beim Verbindungsaufbau

Code:
$optin = array(\PDO::MYSQL_ATTR_INIT_COMMAND => " SET NAMES utf8");
$obj = new \PDO("mysql:host={$host};dbname={$database}", $user, $passwd, $optin);

Ich seh übrigens gerade dass, scheinbar außnahmslos, alle exotischen Zeichen korrekt in der DB erscheinen und ich sie vermutlich durch die Konvertierung zerstör...^^

Allerdings weiß ich nicht ob es unvorhergesehene Probleme gibt wenn ich die Zeichen "roh" ausgeb. Wie damals mit &nbsp;

Da hat phpbb geschätzte 10k Zeilen mit UTF-8 Funktionen, verteilt auf mehrere Dateien, wenn es so einfach ist?
 
Zuletzt bearbeitet:
Ein &nbsp; macht, genau wie die Umlaute etc., normalerweise komplett korrekt in der Datenbank gelagert und ausgegeben. Wenn du mit sowas Probleme hattest, dann lag es an deinen "Schutzfunktionen". Ich hab schon häufiger verschiedenste HTML Entitäten 1:1 in der Datenbank gelagert, ohne die kleinsten Probleme.
 
Kann sein dass es an sowas lag.

Hiermit:

$text = preg_replace('/[\x80-\xFF]/', '?', $text);

wurden aktuell alle sauber gespeicherten Exoten in ? konvertiert...


PS: Was ist mit UTF-7 Injections?
 
Zuletzt bearbeitet:
XSS-Angriffe über fehlende Charset-Ankündigung? Also DAS ist nun wirklich kein Problem...
 
Wie ist das bei Asynchron geladenem Content. Angenommen es wird ein Chatfenster geladen ohne charset Header?

Ist es sinnvoll das genutzte charset doppelt zu senden? Einmal vom Server selbst und einmal über php? Als Fallback fals man irgendwann mal den Server wechselt und nicht alles anpassen möchte?
 
Zuletzt bearbeitet:
Es schadet nicht, aber so wie ich gewisse Abschnitte auf php.net gerade verstehe sendet PHP wohl standardmäßig eh einen Header mit Content-type text/html und Charset UTF-8.
Außerdem bezweifle ich, dass die großen und beliebten Webserver nicht bereits in den Standardeinstellungen einen Charset Header schicken.

Zu guter letzt: Warum sollte man, um bei deinem Beispiel zu bleiben, das ganze Chatfenster asynchron direkt als HTML laden? Ein JSON-String, der nur die Nachrichten enthält, wäre deutlich effektiver weil kleiner. Bandbreite ist viel teurer als Rechenleistung.
 
Ich hab jetzt nicht alles gelesen, aber ich hatte das Problem, als ich die gesamte DB auf UTF-8 gestellt hatte, dass beim Auslesen eines Datensatzes die Ausgabe der Daten falsch war bzw. da diese komischen Fragezeichenrauten bei Sonderzeichen kamen.

das hatte ich folgendermaßen gelöst
PHP:
function dbconnect()
{
	$dbserver = 'localhost';
	$dbuser = 'testuser';
	$dbpassword = '******';
	$dbname = 'test';
	
	$dbconnect = mysql_connect($dbserver,$dbuser,$dbpassword)
	or die( "Verbindung zur Datenbank fehlgeschlagen. <br />" .mysql_error());
	
	$dbchoose = mysql_select_db($dbname)
	or die("Datenbank konnte nicht ausgewählt werden und existiert vielleicht nicht. <br />" .mysql_error());
	
	//UTF-8 Ausgabefehler verhindern
	mysql_query("SET NAMES 'utf8'");
}

Die letzte Zeile löst das Ausgabeproblem
 
Aus der php.ini:
; PHP's default character set is set to empty.
; http://php.net/default-charset
;default_charset = "UTF-8"


Zu guter letzt: Warum sollte man, um bei deinem Beispiel zu bleiben, das ganze Chatfenster asynchron direkt als HTML laden? Ein JSON-String, der nur die Nachrichten enthält, wäre deutlich effektiver weil kleiner. Bandbreite ist viel teurer als Rechenleistung.

Als erstes wird das Chatfenster initialisiert. Der Austausch der Nachrichten läuft dann natürlich im JSON Format..

@TE
Prepared Statements sind eigentlich die einzig richtige Wahl.
 
Zuletzt bearbeitet:
Liebe CB Gemeinde, ich habe das Problem dank eurer Hilfe gelöst. Konnte mich aus beruflichen Gründen nicht eher zurück melden.
 
Zurück
Oben