PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr

PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr (https://www.php-resource.de/forum/)
-   Apps und PHP Script Gesuche (https://www.php-resource.de/forum/apps-und-php-script-gesuche/)
-   -   [PHP] Multibyte-taugliches wordwrap? (https://www.php-resource.de/forum/apps-und-php-script-gesuche/103314-php-multibyte-taugliches-wordwrap.html)

Quetschi 29-08-2012 13:49

[PHP] Multibyte-taugliches wordwrap?
 
Hallo,

hat jemand einen Schnipsel parat, der die Funktionalität von wordwrap() umsetzt und dabei Multibyte-Strings verlässlich UND halbwegs performant bearbeitet?

Jedes Schnipsel das ich bis jetzt auf php.net oder stackoverflow.com gefunden hab, hat entweder nicht zuverlässig gearbeitet oder aber schon für kurze Strings ein paar Sekunden gebraucht! :o

AmicaNoctis 29-08-2012 21:08

Hallo,

meinst du UTF-8 oder andere UTFs? Bei UTF-8 kannst du das eingebaut wordwrap verwenden, da der Byte code 0x20 nicht in anderen Sequenzen vorkommen darf, zumindest nicht in gültigen. Aus ungültigen Sequenzen könnten also schlimmstenfalls andere ungültige Sequenzen werden. Ob das ein Sicherheitsrisiko darstellt, musst du kontextabhängig entscheiden.

Bei den UTF-16/32-BE/LE-Codierungen kannst du dir auch mit explode was selber basteln oder den String mit for durchrattern (letzteres sollte schneller gehen als Array-Operationen). Du musst an sich nur die Byte Order erkennen und entsprechend kannst du dann auch nach 0x0020, 0x2000, 0x00000020 oder 0x20000000 suchen.

Gruß,

Amica

wahsaga 29-08-2012 21:13

Zitat:

Zitat von AmicaNoctis (Beitrag 662851)
Bei UTF-8 kannst du das eingebaut wordwrap verwenden, da […]

Wenn es nur um das Ersetzen von Leerzeichen durch Umbrüche geht, vielleicht. (Dazu bräuchte man es aber nur in Sonderfällen, denn an Leerzeichen umbrechen kann HTML gut selber*.)

Aber wordwrap kann auch innerhalb eines zu langen Wortes Umbrüche erzwingen – und da wird’s bei Mehrbyte-Kodierungen schnell haarig …


* btw, wenn man’s nur dafür braucht, dass zu lange Wörter im Browser umgebrochen werden – da kann man m.E. besser die CSS-Eigenschaft word-wrap:break-word für benutzen.

AmicaNoctis 29-08-2012 21:17

Okay, das ist aber auch in UTF-8 mit einer einzigen Bedingung abgehandelt: Es darf nie ein Umbruch vor einem Byte aus dem Bereich 0x80 bis 0xbf (beides inklusive) eingefügt werden. Alles andere ist erlaubt. In den anderen UTFs ist es wegen der gleichen Bytelänge der Zeichen noch simpler.

Quetschi 29-08-2012 21:22

Hallo AmicaNoctis,

Es geht tatsächlich nur um UTF8-Strings. Das eingebaute wordwrap versagt bei mir allerdings sobald Zeichen in String vorkommen, die mehr als ein Byte belegen. Hier wird der String dann jeweils zu früh umgebrochen. :dontknow:

PHP-Code:

mb_internal_encoding("UTF-8");
header'content-type: text/plain; charset=utf-8' );

$str "Etwas Text - mal ein e-Zeichen und wieder etwas Text";
echo 
wordwrap($str30); 

bricht nach "e-Zeichen" um.

PHP-Code:

mb_internal_encoding("UTF-8");
header'content-type: text/plain; charset=utf-8' );

$str "Etwas Text - mal ein €-Zeichen und wieder etwas Text";
echo 
wordwrap($str30); 

bricht nach "mal ein" um.


EDIT:
@wahsaga
Den vierten Parameter von wordwrap verwende ich nicht. Es soll also nur zwischen zwei Wörtern umgebrochen werden.
Verwendet wird es für Plain-Text-Mails. Die Mails werden mit SwiftMailer erstellt - jedoch versagt auch hier die eingebaute Funktion, die die Mail auf maximale Zeilenlänge von 78-Zeichen beschränken soll.


Nochmal Edit:
Getestet unter 5.3.9 und 5.2.13

h3ll 29-08-2012 21:38

UTF-8 Wordwrap | Milian Wolff

Quetschi 29-08-2012 22:07

@h3ll

Das Snippet hatte ich auch schon gefunden - aber irgendwas hat da nicht gepasst.

Ich schau es mir aber nochmal in Ruhe an.

h3ll 29-08-2012 22:10

Darf ich fragen, wofür man das braucht?

Quetschi 29-08-2012 22:35

@h3ll

Hatte es in Post#5 schon im Edit geschrieben:
Zitat:

Verwendet wird es für Plain-Text-Mails. Die Mails werden mit SwiftMailer erstellt - jedoch versagt auch hier die eingebaute Funktion, die die Mail auf maximale Zeilenlänge von 78-Zeichen beschränken soll.

Quetschi 29-08-2012 22:48

@h3ll

Die von dir verlinkte Funktion versagt leider auch bei diversen Strings.

h3ll 29-08-2012 22:57

Zend_Text_MultiByte::wordWrap()

wahsaga 29-08-2012 23:26

Zitat:

Zitat von Quetschi (Beitrag 662854)
PHP-Code:

$str "Etwas Text - mal ein e-Zeichen und wieder etwas Text";
echo 
wordwrap($str30); 

bricht nach "e-Zeichen" um.

PHP-Code:

$str "Etwas Text - mal ein €-Zeichen und wieder etwas Text";
echo 
wordwrap($str30); 

bricht nach "mal ein" um.

Mein hingehackter Versuch:
PHP-Code:

function wordwrap_utf8_primitive($str$length$break) {
  
$parts explode(' '$str);
  
$return = array('');
  
$i 0;
  foreach(
$parts as $word) {
    if(
mb_strlen($return[$i], 'UTF-8') + mb_strlen($word'UTF-8') <= $length) {
      
$return[$i] .= $word ' ';
    }
    else {
      
$return[$i] = rtrim($return[$i]); // letztes Leerzeichen wieder entfernen
      
$return[++$i] = $word ' ';
    }
  }
  return 
rtrim(join($break$return));
}

$str "Etwas Text - mal ein e-Zeichen und wieder etwas Text";
echo 
wordwrap_utf8_primitive($str30'<br>');  

$str "Etwas Text - mal ein €-Zeichen und wieder etwas Text";
echo 
wordwrap_utf8_primitive($str30'<br>');

// Ausgabe:

// Etwas Text - mal ein e-Zeichen
// und wieder etwas Text

// Etwas Text - mal ein €-Zeichen
// und wieder etwas Text 

Geht sicherlich eleganter, aber tut für den präsentierten Testfall erst mal was es soll.

Quetschi 30-08-2012 00:55

Zitat:

Zitat von h3ll (Beitrag 662862)
Zend_Text_MultiByte::wordWrap()

Hatte ich mir ebenfalls schon geholt und versagt ebenso in einigen Fällen. Die Google-Suche bringt da auch einiges zum Vorschein.

@wahsaga
So einen Ansatz hatte ich auch schon im Kopf - teste ich morgen - für heut reichts mir :-)

Thank you very much!

Edit:
Wenn im Ausgangstext ein Zeilenumbruch vorkommt, macht die Funktion danach evtl. nicht richtig weiter, oder? Schau ich mir morgen an - da kann man ja noch entsprechend drauf reagieren.

wahsaga 30-08-2012 11:54

Zitat:

Zitat von Quetschi (Beitrag 662864)
Wenn im Ausgangstext ein Zeilenumbruch vorkommt, macht die Funktion danach evtl. nicht richtig weiter, oder?

Natürlich nicht – sie hat aus gutem Grund “primitive” im Namen :-)

Wobei man erst mal definieren müsste, wie die Funktion darauf reagieren soll, bzw. schauen, wie das originale wordwrap das macht (und ob das das gewünschte Verhalten ist).

Vielleicht wäre es sinnvoll, den Eingabetext erst mal in Zeilen aufzusplitten – und jede von denen dann einzeln zu behandeln. Das ergibt auch von der Logik her vermutlich den meisten Sinn – innerhalb von Zeilen wird bei Länge x umgebrochen; schon bestehende Umbrüche werden aber so übernommen, wie sie sind.

Quetschi 30-08-2012 12:17

Zitat:

Zitat von wahsaga (Beitrag 662873)
...sie hat aus gutem Grund “primitive” im Namen :-)

Aufgrund des Verfassers des Scripts? :confused:


;)


Alle Zeitangaben in WEZ +2. Es ist jetzt 03:23 Uhr.

Powered by vBulletin® Version 3.8.2 (Deutsch)
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0
[c] ebiz-consult GmbH & Co. KG