Matze: wie funktioniert eine Callback-Funktion?

Hallo!

Es geht mir darum, den Benutzern verschiedene Möglichkeiten zur Formatierung von Eingaben zu geben.
Sowas wie hier im Forum die Liste mit Link, Bild, HTML, CSS usw. über dem Eingabefeld.

Vor einiger Zeit hab ich mal gelesen, dass das mit einer Callback-Funktion gemacht wird anstatt mehrere Aufrufe von preg_replace hintereinander zu setzen.

Leider versteh ich nicht was das ist und wie man damit arbeitet.
Könnte es mir bitte jemand erklären?

Vielen Dank!

  1. Hi!

    Leider versteh ich nicht was das ist und wie man damit arbeitet.

    Hast Du die Erklärung auf php.net, net(t) gefunden, oder net verstanden?

    off:PP

    --
    "You know that place between sleep and awake, the place where you can still remember dreaming?" (Tinkerbell)
    1. Hallo Peter Pan!

      Leider versteh ich nicht was das ist und wie man damit arbeitet.

      Hast Du die Erklärung auf php.net, net(t) gefunden, oder net verstanden?

      Nicht verstanden.

      Grüße, Matze

      1. Hi!

        Hast Du die Erklärung auf php.net, net(t) gefunden, oder net verstanden?
        Nicht verstanden.

        Was konkret ist dir unklar?

        Eine Callback-Funktion ist erst einmal eine ganz normale Funktion, wie jede andere auch. Das Besondere ist, dass sie nicht direkt aufgerufen wird, sondern dass nur ein Verweis an sie übergeben wird, damit die eigentlich aufgerufenen Funktion sie aufrufen kann. Beispiel array_walk():

        $array = array(...);  
        array_walk($array, "trim");
        

        array_walk() durchläuft das übergebene Array und wendet auf jedes Element die Funktion trim() an. Das ist der Callback. Unter PHP ist es so, dass man den Namen der Callback-Funktion als String übergibt (im einfachsten Fall - bei OOP ist es etwas komplexer). In anderen, kompilierenden Systeme übergibt man einen Zeiger oder eine Referenz auf die Callback-Funktion.

        Ausgeschrieben sähe array_walk() ungefähr (vereinfacht) so aus:

        function array_walk(&$array, $callback) {  
          foreach ($array as $key => $value)  
            $array[$key] = $callback($value);  
        }
        

        Im Falle von "trim" ergäbe das:

          foreach ($array as $key => $value)  
            $array[$key] = trim($value);
        

        Lo!

        1. Hallo,

          Was konkret ist dir unklar?

          Danke für deine ausführliche Erklärung.
          Nach bisschen rumspielen ohne Erfolg fühl ich mich aber immernoch nicht klüger :(

            
          // Eingabe aus einem Textfeld  
          $string = $_POST['input'];  
          // Array mit den zu suchenden Zeichenketten  
          $arrneedle = array("#\[link=(.*?)\](.*?)\[/link\]#si", "#\[b\](.*?)\[/b\]#si");  
          // Array mit den ersetzten Zeichenketten  
          $arrreplace = array('<a href="\1">\2</a>', '<b>\1</b>');  
          // Callback auf preg_replace()  
          $string = preg_replace_callback($arrneedle, preg_replace($arrneedle, $arrreplace, $string), $string);
          

          Das gibt mir folgenden Fehler:
          Warning: preg_replace_callback() [function.preg-replace-callback]: Requires argument 2, '<a href="\1">\2</a>::<b>\1</b>', to be a valid callback in...

          Wieso ist das so?
          Ich dachte mit jeder gefundenen Zeichenkette wird damit preg_replace aufgerufen und der Teil ersetzt.

          Grüße, Matze

          1. Hi!

            $string = preg_replace_callback($arrneedle, preg_replace($arrneedle, $arrreplace, $string), $string);[/code]
            Das gibt mir folgenden Fehler:
            Warning: preg_replace_callback() [function.preg-replace-callback]: Requires argument 2, '<a href="\1">\2</a>::<b>\1</b>', to be a valid callback in...

            Wieso ist das so?
            Ich dachte mit jeder gefundenen Zeichenkette wird damit preg_replace aufgerufen und der Teil ersetzt.

            Das was du machst ist quasi wie folgt:

            foo(bar())

            Solche verschachtelte Funktionsaufrufe werden immer von innen nach außen aufgelöst. Also wird zuerst bar() aufgerufen - was auch immer es macht - und das zurückgegebenen Ergebnis davon wird als Argument von foo() verwendet. Es ist _nicht_ so, dass foo() aufgerufen wird und das dann bar() aufruft. - Das jedenfalls ist kein Callback.

            preg_replace_callback() erwartet als zweiten Parameter die Angabe einer Callback-Funktion, was im einfachsten Fall der Name einer Funktion ist, der als String übergeben wird. Im foo-bar-Beispiel müsste also bar() einen String mit einem Funktionsnamen liefern. Wenn bar() selbst die Callback-Funktion sein soll, wäre foo("bar") ein gültiger Aufruf oder aber auch foo(qux()), mit function qux() { return "bar"; }.

            Das willst du aber gar nicht so verwenden. Allerdings sehe ich anhand deines Beispiels nicht, warum du einen Callback benötigst und nicht einfach nur preg_replace() aufrufen willst.

            Ein Beispiel für eine Callback-Anwendung wäre:

            function anchor($matched) {  
              return sprintf('<a href="%s">%s</a>', htmlspecialchars($matched[1]), htmlspecialchars($matched[2]));  
            }  
              
            $result = preg_replace_callback('#\[url=([^]]*)]([^[]*)\[/url]#', 'anchor', $text);
            

            Das was statt [url=...]...[/url] eingesetzt werden soll, lässt sich nur recht umständlich als RegExp formulieren, wenn man die HTML-Sonderzeichen mit berücksichtigen will (das was htmlspecialchars() macht). Deswegen lasse ich mit preg_replace_callback() nur suchen und die Behandlung des Ergebnisses übernimmt die Funktion anchor(). In ihr könnte nun beispielsweise auch noch eine unterschiedliche Behandlung von URLs implementiert werden, die mit http:// oder ftp:// oder ohne oder sonstwie angegeben wurden. All dies als einen einzigen RegExp zu formulieren, dürfte auch nicht gerade übersichtlich werden.

            Lo!

            1. Hallo,

              Das willst du aber gar nicht so verwenden. Allerdings sehe ich anhand deines Beispiels nicht, warum du einen Callback benötigst und nicht einfach nur preg_replace() aufrufen willst.

              mh das merk ich auch gerade. Vielleicht hatte ich da nur einen Floh im Ohr?!

              Deswegen lasse ich mit preg_replace_callback() nur suchen und die Behandlung des Ergebnisses übernimmt die Funktion anchor().

              Also doch mit Callback? Jetzt bin ich verwirrt.
              Nach deinem Beispiel müsste ich also preg_replace_callback mit jeder RegExp aufrufen? Oder halt in einem Array?
              Also einmal für z.B. Links, einmal für Bilder usw. und in der Funktion anchor() wird der String dann bearbeitet?
              Wird eigentlich der gesamte String an anchor() geschickt?

              Und dann noch eine andere Frage.
              Ist es aus irgendwelchen Gründen sinnvoller preg_replace_callback und eine Funktion mit vielen sprintf() zu benutzen oder alleine preg_replace mit 2 Arrays (suchen & ersetzen)?

              Danke für deine Hilfe!

              Matze

              1. Hi!

                Deswegen lasse ich mit preg_replace_callback() nur suchen und die Behandlung des Ergebnisses übernimmt die Funktion anchor().

                Also doch mit Callback? Jetzt bin ich verwirrt.

                'tschuldigung, ich hatte nicht so genau hingesehen, welches Muster du da verwendest. Ja, dafür bietet sich - wenn du es richtig machen willst - die Verwendung einer Callback-Funktion an. Wenn du in deinem Beispiel nur preg_replace() verwendest, hast du eine XSS-Lücke, weil du die HTML-Sonderzeichen nicht behandelst.

                Nach deinem Beispiel müsste ich also preg_replace_callback mit jeder RegExp aufrufen? Oder halt in einem Array?

                Ein mehrfacher Aufruf, also für jedes Suchmuster einer wäre sinnvoll, denn als Callback kann man nur einen einzelnen angeben. Das heißt, der Callback müsste für alle Suchmuster gleichermaßen umgehen können, wenn du ein Array an Suchmustern verwenden wolltest.

                Also einmal für z.B. Links, einmal für Bilder usw. und in der Funktion anchor() wird der String dann bearbeitet?

                Ja, für Links. Für Bilder wäre dann eine image()-Funktion angebracht und für usw. eine usw()-Funktion :-)

                Wird eigentlich der gesamte String an anchor() geschickt?

                Wie immer bei den preg-Funktionen und bei Gruppierungen bekommst du die Gruppenergebnisse in $n (du verwendest \n, besser wäre $n), wobei in n=0 der auf das gesamte Muster passende Teil steht und in n=1..n die Ergebnisse der Gruppen. In der Callback-Funktion stehen dir die Werte als Elemente des übergebenen Arrays zur Verfügung, also gemäß meinem Beispiel wäre der Inhalt von $matched

                Array (
                    [0] => [url=http://example.com/foobar]link & so weiter[/url]
                    [1] => http://example.com/foobar
                    [2] => link & so weiter
                )

                bei einer Übergabe von

                foo [url=http://example.com/foobar]link & so weiter[/url] bar

                als zu durchsuchender Zeichenfolge. In $matched[0] hast also du die gesamte Fundstelle, nicht aber den gesamten zu durchsuchenen Text.

                Ist es aus irgendwelchen Gründen sinnvoller preg_replace_callback und eine Funktion mit vielen sprintf() zu benutzen oder alleine preg_replace mit 2 Arrays (suchen & ersetzen)?

                Kommt auf die Aufgabenstellung an. Wenn du nur einfache Ersetzungen benötigst, dann brauchst du keine Callback-Funktion. Sine die Ersetzungsregeln umfangreicher, kommst du an einer spezialisierten Funktion kaum vorbei.

                Lo!

                1. Hey!

                  'tschuldigung, ich hatte nicht so genau hingesehen, welches Muster du da verwendest. Ja, dafür bietet sich - wenn du es richtig machen willst - die Verwendung einer Callback-Funktion an.

                  Mh und wie müsste die Funktion dann aussehen? Könnten wir das vielleicht ein Stück für mich erarbeiten?

                  Wenn du in deinem Beispiel nur preg_replace() verwendest, hast du eine XSS-Lücke, weil du die HTML-Sonderzeichen nicht behandelst.

                  Inwiefern? Was kann mir da passieren?
                  Und wieso muss ich beim suchen und ersetzen HTML-Sonderzeichen beachten? Ich dachte die spielen erst bei der Ausgabe eine Rolle?

                  Ein mehrfacher Aufruf, also für jedes Suchmuster einer wäre sinnvoll, denn als Callback kann man nur einen einzelnen angeben. Das heißt, der Callback müsste für alle Suchmuster gleichermaßen umgehen können, wenn du ein Array an Suchmustern verwenden wolltest.

                  Ja das versteh ich nicht.
                  Wenn die Callback-Funktion mit allem gleich umgeht müsste ich ja in der Funktion wieder ein Array bereit halten in dem alle möglichen RegExp stehen um dagegen zu vergleichen, oder?

                  Ja, für Links. Für Bilder wäre dann eine image()-Funktion angebracht und für usw. eine usw()-Funktion :-)

                  Unterscheiden die sich denn so gravierend? Sollte man für sowas dann auch gleich eine Klasse anlegen?

                  Danke und Grüße, Matze

                  1. Hi!

                    'tschuldigung, ich hatte nicht so genau hingesehen, welches Muster du da verwendest. Ja, dafür bietet sich - wenn du es richtig machen willst - die Verwendung einer Callback-Funktion an.
                    Mh und wie müsste die Funktion dann aussehen? Könnten wir das vielleicht ein Stück für mich erarbeiten?

                    So wie mein anchor-Beispiel.

                    Wenn du in deinem Beispiel nur preg_replace() verwendest, hast du eine XSS-Lücke, weil du die HTML-Sonderzeichen nicht behandelst.
                    Inwiefern? Was kann mir da passieren?

                    Du willst ja nicht, dass HTML eingegeben werden kann, weswegen du ja auf BB-Code ausweichst und damit die Eingaben mit der stark vereinfachten Syntax in ihren Möglichkeiten beschränkst. Du möchtest nun sicher nicht, dass jemand <script> und anderes Zeug eingibt und damit deine Seite nach Belieben umgestaltet werden kann. Deswegen müssen alle Zeichen mit Sonderbedeutung in HTML in ihrer maskierten Form notiert werden => htmlspecialchars().

                    Und wieso muss ich beim suchen und ersetzen HTML-Sonderzeichen beachten? Ich dachte die spielen erst bei der Ausgabe eine Rolle?

                    Beim Ersetzen verwendest du bereits HTML-Code, in den du die Suchbruchstücke einbettest. Zu diesem Zeitpunkt muss schon syntaktisch korektes HTML entstehen, weil du später nicht mehr unterscheiden kannst, ob ein < zu einem von dir gewollten Tag-Beginn gehört oder vom Anwender eingegeben wurde.

                    Ein mehrfacher Aufruf, also für jedes Suchmuster einer wäre sinnvoll, denn als Callback kann man nur einen einzelnen angeben. Das heißt, der Callback müsste für alle Suchmuster gleichermaßen umgehen können, wenn du ein Array an Suchmustern verwenden wolltest.

                    Ja das versteh ich nicht.
                    Wenn die Callback-Funktion mit allem gleich umgeht müsste ich ja in der Funktion wieder ein Array bereit halten in dem alle möglichen RegExp stehen um dagegen zu vergleichen, oder?

                    Ja, und genau das ist ja nicht sehr sinnvoll. Du ermittelst erst alle Muster, wirfst sie in einen Topf (eine gemeinsame Callback-Funktion) und musst sie dann wieder erst voneinander unterscheiden, also mehr oder weniger nochmal neu erkennen. Dann lieber eine Einzelbearbeitung.

                    Ja, für Links. Für Bilder wäre dann eine image()-Funktion angebracht und für usw. eine usw()-Funktion :-)
                    Unterscheiden die sich denn so gravierend? Sollte man für sowas dann auch gleich eine Klasse anlegen?

                    Ja, natürlich. Die Syntax vom a-Element unterscheidet sich vom img-Element und das wiederum vom usw.-Element. Einige sind gleich (zum Beispiel b, u, i), für die kannst du eine gemeinsame Funktion erstellen (der dann über eine dritte RegExp-Gruppe mitgeteilt werden sollte, welches der Elemente vorliegt, um das richtige HTML-Element in die Ausgabe zu bringen).

                    Lo!

                    1. Hey!

                      ... Du möchtest nun sicher nicht, dass jemand <script> und anderes Zeug eingibt und damit deine Seite nach Belieben umgestaltet werden kann. Deswegen müssen alle Zeichen mit Sonderbedeutung in HTML in ihrer maskierten Form notiert werden => htmlspecialchars().
                      Beim Ersetzen verwendest du bereits HTML-Code, in den du die Suchbruchstücke einbettest. Zu diesem Zeitpunkt muss schon syntaktisch korektes HTML entstehen, weil du später nicht mehr unterscheiden kannst, ob ein < zu einem von dir gewollten Tag-Beginn gehört oder vom Anwender eingegeben wurde.

                      Ich schreibe die Ausgabe im Moment so:

                      echo meineFunktion(nl2br(htmlspecialchars($_POST['input'])));

                      Wie die Funktion aussieht habe ich oben bereits gepostet.
                      Eigentlich hab ich doch dabei keine Probleme die HTML-eigenen Tags vom BB-Code zu trennen?!
                      htmlspecialchars greift ja vor der Funktion zum suchen & ersetzen.

                      Ja, und genau das ist ja nicht sehr sinnvoll. Du ermittelst erst alle Muster, wirfst sie in einen Topf (eine gemeinsame Callback-Funktion) und musst sie dann wieder erst voneinander unterscheiden, also mehr oder weniger nochmal neu erkennen. Dann lieber eine Einzelbearbeitung.

                      Genau dieses "doppelt-gemoppelte" kam mir halt auch sehr merkwürdig vor.

                      Ja, natürlich. Die Syntax vom a-Element unterscheidet sich vom img-Element und das wiederum vom usw.-Element. Einige sind gleich (zum Beispiel b, u, i), für die kannst du eine gemeinsame Funktion erstellen (der dann über eine dritte RegExp-Gruppe mitgeteilt werden sollte, welches der Elemente vorliegt, um das richtige HTML-Element in die Ausgabe zu bringen).

                      Also müsste ich so vorgehen?

                        
                      echo meineFunktion(nl2br(htmlspecialchars($_POST['input'])));  
                      function meineFunktion($string){  
                          // für Links  
                          $result = preg_replace_callback(REGEXP, 'anchor', $string);  
                          // für i, u, b  
                          $result = preg_replace_callback(REGEXP, 'iub', $string);  
                          // für images  
                          $result = preg_replace_callback(REGEXP, 'images', $string);  
                      }  
                      function anchor($array){  
                          return sprintf('<a href="%s">%s</a>', $array[1], $array[2]);  
                      }  
                      function iub($array){  
                          // hier müsste ich jetzt wohl irgendwie prüfen ob i, u oder b  
                      }  
                      function images($array){  
                          return sprintf('<img src="%s" alt="%s" />', $array[1], $array[2]);  
                      }  
                      
                      

                      Ich hab gerade gemerkt, dass deine RegExp anders aussieht als meine.
                      Deine:
                      '#\[url=([^]]*)]([^[]*)\[/url]#'
                      Meine:
                      "#\[link=(.*?)\](.*?)\[/link\]#si"

                      Da ich nicht so fit damit bin und meine RegExp immer mit mehr Glück als Verstand zusammen schustere würde ich gern wissen wo da jetzt genau die Unterschiede liegen. Ich geh davon aus, dass deine die 'bessere' ist.

                      Danke und Grüße, Matze

                      1. Hi!

                        Ich schreibe die Ausgabe im Moment so:
                        echo meineFunktion(nl2br(htmlspecialchars($_POST['input'])));

                        Das wusste ich nicht, dass du das schon vorher machst. In dem Fall brauchst du dann doch kein Callback, weil du nun nur noch ein einfaches Einfügen beim Ersetzen benötigst und kannst wieder zum einmaligen Aufruf von preg_replace() mit zwei Arrays übergehen. Allerdings ist das dann stets davon abhängig, dass die Daten schon vorher ge-htmlspecialchars()t wurden, was du beim Wiederverwenden in anderen Projekten berücksichtigen musst. Für sauberer hielte ich es, wenn du bei der Callback-Methode inklusive htmlspecialchars() bliebest, dafür das vorhergehende htmlspecialchars() raushaust und das nl2br() anschließend anwendest. Für jetzt jedenfalls führen dich beide Methoden sicher ans Ziel.

                        // für i, u, b

                        $result = preg_replace_callback(REGEXP, 'iub', $string);
                        function iub($array){
                            // hier müsste ich jetzt wohl irgendwie prüfen ob i, u oder b
                        }

                          
                        Nee, "einfach" im Muster eine Gruppe einfügen und die verwenden.  
                          
                        \[([uib])([^[]\*)\[/[uib]]  
                          ^     ^  
                          
                        Wobei ich jetzt grade beim Musterzusammenbau sehe, dass nun auch [u]...[/i] passt, was nicht sein soll. Also müsstest du zwar einzeln prüfen aber die gleiche Callback-Funktion nehmen:  
                          
                        \[(u)]([^[]\*)\[/u]  
                          ^ ^  
                          
                        und das dann auch noch für i und b.  
                          
                        Somit hast du nun zwei Gruppen, wovon die erste (markierte) je nach Muster u, i oder b enthält und die zweite den zu formatierenden Text.  
                          
                        
                        > Ich hab gerade gemerkt, dass deine RegExp anders aussieht als meine.  
                        > Deine:  
                        > `'#\[url=([^]]*)]([^[]*)\[/url]#'`{:.language-php}  
                        > Meine:  
                        > `"#\[link=(.*?)\](.*?)\[/link\]#si"`{:.language-php}  
                        >   
                        > Da ich nicht so fit damit bin und meine RegExp immer mit mehr Glück als Verstand zusammen schustere würde ich gern wissen wo da jetzt genau die Unterschiede liegen. Ich geh davon aus, dass deine die 'bessere' ist.  
                          
                        Nicht unbedingt, es ist nur ein anderer Weg. Du verwendest ein ? um die Suche ungierig zu gestalten, ich nehme "alles was kein Abschlusszeichen ist".  
                          
                        Beispiel am Ausschnitt: \[url=([^]]\*)]  
                          
                        \[url= dürfte klar sein.  
                        ( Gruppenanfang  
                        [ Zeichenklassenanfang  
                        ^ ein ^ als erstes Zeichen ist eine Negation  
                        ] Ein ]. [Wenn das \] als erstes nach dem \[ oder ^ steht, muss man es nicht maskieren](http://www.php.net/manual/en/regexp.reference.squarebrackets.php).  
                        ] Ende der Zeichenklasse  
                        \* beliebig viele  
                        ) Gruppenende  
                        ] danach soll ein ] stehen  
                          
                        Die Zeichenklasse bedeutet hier "alles was kein ] ist" und passt damit auf alles zwischen [url= und dem nächsten auftretenden ] und ist damit auch ungierig.  
                          
                        Von den Modifizierern kann man das s weglassen, weil ja bei meinem Muster kein . enthalten ist, für den es wirksam wäre. Das case\_insensitive-i müsste auch bei meinem noch hinzukommen, damit es auf die Groß-/Klein-Schreibweise der BB-Tags wirken kann.  
                          
                          
                        Lo!
                        
                        1. Hey!

                          Ich schreibe die Ausgabe im Moment so:
                          Das wusste ich nicht, dass du das schon vorher machst.

                          Sorry, hätte ich erwähnen sollen.

                          In dem Fall brauchst du dann doch kein Callback

                          Du machst mich irgendwie irre ;)
                          Callback ja, Callback nein... was denn nun?

                          ... weil du nun nur noch ein einfaches Einfügen beim Ersetzen benötigst

                          Läuft es darauf nicht immer hinaus? Also zumindest von meinem 'Problem' mit dem BBCode ausgehend?
                          War denn mein Beispiel mit der Callback-Funktion richtig, damit ich es als 'verstanden' abhaken kann?^^

                          Allerdings ist das dann stets davon abhängig, dass die Daten schon vorher ge-htmlspecialchars()t wurden, was du beim Wiederverwenden in anderen Projekten berücksichtigen musst. Für sauberer hielte ich es, wenn du bei der Callback-Methode inklusive htmlspecialchars() bliebest, dafür das vorhergehende htmlspecialchars() raushaust und das nl2br() anschließend anwendest.

                          Mh irgendwie bin ich da anderer Meinung.
                          Ich halte echo meineFunktion(nl2br(htmlspecialchars($_POST['input']))); für 'sauberer' als echo meineFunktion($string); .
                          Warum? So sehe ich in der Ausgabe ganz genau wie die Daten be(/miss)handelt werden.
                          Im zweiteren Fall, muss ich mich immer darauf verlassen, dass die Funktion alles nötige erledigt. Sowas mag ich nicht.

                          Bitte nenn mir sonst einen Grund der dafür spricht.

                          Für jetzt jedenfalls führen dich beide Methoden sicher ans Ziel.

                          Das beruhigt mich doch sehr. Ich dachte bislang ich bin völlig auf dem Holzweg.

                          Danke für deine ausführliche Erklärung zur RegExp!
                          Wenn ich dich richtig verstanden habe, gleichen sich unsere beiden bis auf das 's'. Das beruhigt mich auch sehr! :)

                          Danke und Grüße, Matze

                          1. Hi!

                            In dem Fall brauchst du dann doch kein Callback
                            Du machst mich irgendwie irre ;)
                            Callback ja, Callback nein... was denn nun?

                            Es kommt drauf an. Einfache Ersetzungen brauchen keine Callback-Funktion, für komplexere Vorgänge ist es sinnvoll eine zu verwenden. Deine Version mit vorangehendem htmlspecialchars() ist eine einfache Ersetzung, meine mit dem eingebauten htmlspecialchars() wäre ein komplexerer Vorgang.

                            ... weil du nun nur noch ein einfaches Einfügen beim Ersetzen benötigst
                            Läuft es darauf nicht immer hinaus? Also zumindest von meinem 'Problem' mit dem BBCode ausgehend?

                            Nö, wie gesagt, kommt auf die Anforderung drauf an.

                            War denn mein Beispiel mit der Callback-Funktion richtig, damit ich es als 'verstanden' abhaken kann?^^

                            Von deiner Warte ausgehend, ja.

                            Allerdings ist das dann stets davon abhängig, dass die Daten schon vorher ge-htmlspecialchars()t wurden, was du beim Wiederverwenden in anderen Projekten berücksichtigen musst. Für sauberer hielte ich es, wenn du bei der Callback-Methode inklusive htmlspecialchars() bliebest, dafür das vorhergehende htmlspecialchars() raushaust und das nl2br() anschließend anwendest.

                            Mh irgendwie bin ich da anderer Meinung.
                            Ich halte echo meineFunktion(nl2br(htmlspecialchars($_POST['input']))); für 'sauberer' als echo meineFunktion($string); .
                            Warum? So sehe ich in der Ausgabe ganz genau wie die Daten be(/miss)handelt werden.

                            Wenn man davon ausgeht, dass htmlspecialchars() angewendet auf den gesamten String zum richtigen Ergebnis führt, kannst du so argumentieren.

                            Im zweiteren Fall, muss ich mich immer darauf verlassen, dass die Funktion alles nötige erledigt. Sowas mag ich nicht.
                            Bitte nenn mir sonst einen Grund der dafür spricht.

                            Besser ist es immer erst dann zu behandeln, wenn der Kontextwechsel erfolgt und nicht irgendwann vorher. Je weiter beide Zeitpunkte auseinander liegen, desto unübersichtlicher wird das Ganze.

                            Das ist bei deinen Callback-Funktionen schon der Fall. Wenn man sie sich alleinstehend anschaut, fehlt da die Behandlung. Man kann sie, obwohl sie einigermaßen universell arbeiten, nicht auch für anderen Anwendungsfälle verwenden, ohnen ihnen stets behandelte Daten zu übergeben. Dazu muss man genau wissen, welches Argument wie behandelt werden muss. Schöner wäre es, wenn die Funktionen Rohdaten übergeben bekommen und selbständig die korrekten Maskierungen einfügen.

                            Und noch ein etwas anderes Szenario: Bei Daten, die als Bestandteil in eine URL eingebaut werden sollen, die dann im HTML landet, muss man zwei Behandlungen vornehmen, urlencode() für die Daten und htmlspecialchars() auf die fertige URL. Wenn diese URL-Daten nur ein Teilstring aus dem eingegebenen Text sind, kannst du nicht den gesamten Text urlencode()ieren, weil dann die an den anderen Stellen stehende Zeichen kaputtgehen.

                            Danke für deine ausführliche Erklärung zur RegExp!
                            Wenn ich dich richtig verstanden habe, gleichen sich unsere beiden bis auf das 's'. Das beruhigt mich auch sehr! :)

                            Nicht ganz, bei mir noch ein i hinzu, dann ist beides gleich.

                            Lo!

                        2. ] Ein ]. Wenn das als erstes nach dem [ oder ^ steht, muss man es nicht maskieren].

                          Genau _das_ machst du doch aber am Ende nicht, oder?
                          Also bei deiner RegExp am Ende: ...[/url]#'
                                                                  ^

                          Grüße, Matze

                          1. Hi!

                            ] Ein ]. Wenn das als erstes nach dem [ oder ^ steht, muss man es nicht maskieren].

                            Genau _das_ machst du doch aber am Ende nicht, oder?
                            Also bei deiner RegExp am Ende: ...[/url]#'

                            Da ist es keine Zeichenklasse, weil vor dem [ noch ein \ steht und es "entschärft". Wenn keine Zeichenklasse eingeleitet ist, steht das ] immer für sich selbst und muss nicht (kann aber) maskiert werden.

                            Lo!

      2. Hi Matze!

        Leider versteh ich nicht was das ist und wie man damit arbeitet.

        Hast Du die Erklärung auf php.net, net(t) gefunden, oder net verstanden?

        Nicht verstanden.

        Ok, ich denke dedlfix' sehr ausführliche Antworten mit Beispielen haben Dir bereits weiter geholfen - wenn nicht: zeige hier den Code, den Du geschrieben hast.

        off:PP

        --
        "You know that place between sleep and awake, the place where you can still remember dreaming?" (Tinkerbell)
        1. Hey!

          Ok, ich denke dedlfix' sehr ausführliche Antworten mit Beispielen haben Dir bereits weiter geholfen - wenn nicht: zeige hier den Code, den Du geschrieben hast.

          function formatUserInput($string){  
            $arrneedle = array("#\[link=(.*?)\](.*?)\[/link\]#si",  
                               "#\[b\](.*?)\[/b\]#si",  
                               "#\[u\](.*?)\[/u\]#si",  
                               "#\[i\](.*?)\[/i\]#si");  
            $arrreplace = array('<a href="\1">\2</a>',  
                                '<b>\1</b>',  
                                '<u>\1</u>',  
                                '<i>\1</i>');  
            $string = preg_replace($arrneedle, $arrreplace, $string);  
            return($string);  
          }
          

          Das funktioniert zwar jetzt, aber mein Hintergrundgedanke war ja der, dass man sowas mit einer Callback-Funktion machen sollte.
          Vielleicht ist das was ich da jetzt hab aber auch schon genau das Richtige und die Lösung so üblich nur weiß ich es nicht ;)

          Danke und Grüße, Matze