Stringlänge wenn UTF-8 Zeihen enthalten sind

Pichel64

Grünschnabel
Moin.
Ich verzweifel gerade an einer vermutlich einfachen Aufgabe:
Ein $String welcher UTF-8 Zeichen (in meinem Test kyrillische Zeichen) enthält soll auf eine vorgebene Länge gekürzt werden. Dies scheitert schon an der Berechnung der korrekten Länge da er mir mit folgendem Codeschnipsel immer 96 ausgibt wobie es zumindestens bei mb_strlen ja 24 ergeben sollte.

PHP:
$value = " КЦЯTSCHДTФШКЦЯTSCHДTФШ";
echo strlen($value) . "\n";
echo strlen(utf8_decode($value)) . "\n";
echo strlen(utf8_encode($value)) . "\n";
echo mb_strlen($value) . "\n";

der String: " КЦЯTSCHДTФШКЦЯTSCHДTФШ"
die Ausgabe: " КЦЯTSCHДTФШ КЦЯTSCHДTФШ"

Ich habe auch schon stundenlang rumgesucht, aber entweder die falschen Schlüsselwörter oder auch beim Suchen einen Knoten im Gehirn.

L.G.Pichel64
 
Der String besteht aus HTML-Entities. (Konkret aus den Zeichen "&", "#" usw.) Daran hängt es.

PHP:
<?php // Diese Datei muss in UTF-8 kodiert sein

$value = 'КЦЯTSCHДTФШ КЦЯTSCHДTФШ';

var_dump(
    mb_strlen($value, 'UTF-8'),             // int(23)
    mb_substr($value, 0, 10, 'UTF-8')       // string(15) "КЦЯTSCHДTФ"
);

Woher beziehst du die Daten?
 
Die Daten kommen aus einem varchar Feld der SQL Datenbank und wurden da direkt aus nem Formular gespeichert.

An dem Code passt irgendwas nicht. In der DB sollten keine HTML-Entities abgelegt werden, sondern 1:1 die eingegebenen Daten.

Notfalls musst du sonst die Daten bei der Weiterverarbeitung erst wieder „zurückbauen“ (die Entities wieder in die durch sie repräsentierten Zeichen umwandeln), was ziemlich sinnfrei ist. Die Funktion ist wohl html_entity_decode. Ich rate aber nachdrücklich dazu, die Daten lieber sauberer abzulegen.

- http://php.net/manual/en/function.html-entity-decode.php

Die Kodierung der php muss ich mal suchen, finden, checken. Darauf hab ich noch nie geachtet wenn ich ehrlich bin.

Du solltest immer die Kodierung von Strings, Textformaten, DB-Feldern usw. kennen. (Und die sollte in aller Regel UTF-8 sein.) Wenn du diese Zusammenhänge einmal richtig kennst, ersparst du dir eine Menge Fehlerszenarien damit. Ansonsten enthalten PHP-Quellcode-Dateien – außerhalb von Kommentaren – in der Regel aber nur 7-Bit-ASCII-Zeichen. Wenn sie auch Ausgabe generieren oder lokalisierte Strings enthalten, ist es anders (etwa wegen der Umlaute), aber das hat selten eine Auswirkung auf die Logik/Funktion des Codes.

Worauf ich hinaus will: Die Kodierung der Quellcodedateien solltest du natürlich auch kennen, aber wichtig ist vor allem die Kodierung der Daten, da die in der Regel nicht direkt im Code definiert werden, sondern aus einer DB bezogen werden oder dergleichen. Der verarbeitende Code besteht oft nur aus ASCII-Zeichen, weil man eben auf Englisch programmiert. Das mal (wie in #2) ein russischer String direkt im Code steht, kommt nicht so häufig vor. Mehr bei Beispielcode.
 
Die Funktion ist wohl html_entity_decode
Das Problem ist ja nun, dass die Daten nun schonmal teilweise so in der Datenbank gespeichert sind, und html_entity_decode sollte das korrigieren, tut es aber leider nicht.
Ich habe mal Deinen Code wie folgt ausgeführt:
PHP:
$value = " &#1050;&#1062;&#1071;TSCH&#1044;T&#1060;&#1064; &#1050;&#1062;&#1071;TSCH&#1044;T&#1060;&#1064;";
$value = html_entity_decode($value);
var_dump(
    mb_strlen($value, 'UTF-8')            // int(96)
);

Grundsätzlich finde ich es auch richtig und wichtig alles eindeutig auf UTF-8 umzustellen auch wenn die Webseiten bisher in ISO-8859-1 ausgegeben wurden, nur was mache ich mit den bereits vorhandenen Werten in der Datenbank.
Es fängt doch schon mit den deutschen Umlauten an die bei Umstellung in so ein unschönes Fragezeichen gewandelt werden.
Um alles von Hand in der DB zu ändern ist es schon etwas zu viel.

Welchen Editor verwendest du denn?
Habt Ihr eine Empfehlung und Alternive zu meinem "Phase 5"
 
Zu Phase5:
Laut Internet ist der Zeichensatz dabei nicht wirklich einstellbar (das ist der peinliche Teil :p, nicht das Alter)
Einen HTML-spezifischen Wysiwyg-Editor hab ich leider keinen zum Empfehlen.

Zur DB:

Jedes Vorkommen händisch ausbessern muss man das "nicht" machen, keine Sorge.

Mysql?
Wieviel Tabellen gibts denn ungefähr? Und wieviel Datensätze gesamt (ganz grob. 1000? 1000000?).
Zugriff per PHPmyAdmin oder sogar SSH?
 
PHP:
<?php

$value = " &#1050;&#1062;&#1071;TSCH&#1044;T&#1060;&#1064; &#1050;&#1062;&#1071;TSCH&#1044;T&#1060;&#1064;";
$value = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
var_dump(
    $value,
    mb_strlen($value, 'UTF-8')            // int(24)
);

Bereits bestehende Werte in der DB kannst du mit einem Script konvertieren.

Pseudocode:

Code:
SELECT * FROM ...

foreach (row) {
    content = html_entity_decode(content)
    UPDATE ... SET content = $content WHERE id = $id
}

Natürlich vorher ein Backup machen.

Wenn Umlaute zu Fragezeichen werden, heißt das in der Regel, dass du ISO-8859-1-Daten (oder Windows-1252-Daten) hast, die für UTF-8 gehalten werden. Die müsstest du dann auch konvertieren.

mb_convert_encoding ist eine gute Funktion dafür.

- http://php.net/manual/en/function.mb-convert-encoding.php

Zum Thema Editor siehe zum Beispiel diese Übersicht: http://php-de.github.io/jumpto/editors-ide/

(Ich kann aus eigener Erfahrung PhpStorm (im Abo für ~10 € pro Monat, glaube ich) und NetBeans (frei, nutze ich hauptsächlich) als IDEs empfehlen. Als Editor für „Kleinkram“ nutze ich Geany, weil er etwas mehr kann als der Standardeditor meiner Distribution. Leistungsfähiger sind in dem Bereich wohl Sublime und Atom.)
 

Neue Beiträge

Zurück