[PHP] Multibyte-taugliches wordwrap?

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [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!
    Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
    Schön - etwas Geschichte kann ja nicht schaden.
    Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

  • #2
    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
    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
    Super, danke!
    [/COLOR]

    Kommentar


    • #3
      Zitat von AmicaNoctis Beitrag anzeigen
      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.
      I don't believe in rebirth. Actually, I never did in my whole lives.

      Kommentar


      • #4
        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.
        [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
        Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
        Super, danke!
        [/COLOR]

        Kommentar


        • #5
          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.

          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
          Zuletzt geändert von Quetschi; 29.08.2012, 20:37.
          Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
          Schön - etwas Geschichte kann ja nicht schaden.
          Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

          Kommentar


          • #6
            UTF-8 Wordwrap | Milian Wolff

            Kommentar


            • #7
              @h3ll

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

              Ich schau es mir aber nochmal in Ruhe an.
              Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
              Schön - etwas Geschichte kann ja nicht schaden.
              Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

              Kommentar


              • #8
                Darf ich fragen, wofür man das braucht?

                Kommentar


                • #9
                  @h3ll

                  Hatte es in Post#5 schon im Edit geschrieben:
                  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.
                  Zuletzt geändert von Quetschi; 29.08.2012, 21:38.
                  Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
                  Schön - etwas Geschichte kann ja nicht schaden.
                  Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

                  Kommentar


                  • #10
                    @h3ll

                    Die von dir verlinkte Funktion versagt leider auch bei diversen Strings.
                    Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
                    Schön - etwas Geschichte kann ja nicht schaden.
                    Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

                    Kommentar


                    • #11
                      Zend_Text_MultiByte::wordWrap()

                      Kommentar


                      • #12
                        Zitat von Quetschi Beitrag anzeigen
                        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.
                        I don't believe in rebirth. Actually, I never did in my whole lives.

                        Kommentar


                        • #13
                          Zitat von h3ll Beitrag anzeigen
                          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.
                          Zuletzt geändert von Quetschi; 29.08.2012, 23:59.
                          Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
                          Schön - etwas Geschichte kann ja nicht schaden.
                          Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

                          Kommentar


                          • #14
                            Zitat von Quetschi Beitrag anzeigen
                            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.
                            I don't believe in rebirth. Actually, I never did in my whole lives.

                            Kommentar


                            • #15
                              Zitat von wahsaga Beitrag anzeigen
                              ...sie hat aus gutem Grund “primitive” im Namen :-)
                              Aufgrund des Verfassers des Scripts?


                              Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
                              Schön - etwas Geschichte kann ja nicht schaden.
                              Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

                              Kommentar

                              Lädt...
                              X