LastBoyScout: Platzhalter in einem Text als Schlüsselwort erkennen und ersetzt

Hallo,

Ich möchte in einem Text enthaltene Platzhalter durch Variablen ersetzen und habe mir dazu mangels einer Vorlage etwas zusammengebastelt:

$nutzer = array(  
    array('NAME' => "Max Mustermann", 'ORT' => "Musterstadt"),  
    array('NAME' => "Helga Beispiel", 'ORT' => "Beispielort"),  
    array('NAME' => "Klaus Tester", 'ORT' => "Testdorf") // usw.  
    );  
  
$text = "Hallo %NAME%, wollen uns in %ORT% mal wieder treffen?...";  
  
foreach($nutzer as $values) {  
    $temp = $text;  
    foreach($values as $search => $replace) {  
        $temp = preg_replace("/%" . $search . "%/", $replace, $temp);  
    }  
    $string .= $temp . "<br/>\n";  
}  
  
echo $string;

Es funktioniert soweit auch ganz gut, nur denke ich das ich es bestimmt etwas umständlich gemacht habe und es mit Sicherheit eleganter bzw. einfacher gelöst werden könnte?

  1. @@LastBoyScout:

    nuqneH

    Es funktioniert soweit auch ganz gut, nur denke ich das ich es bestimmt etwas umständlich gemacht habe und es mit Sicherheit eleganter bzw. einfacher gelöst werden könnte?

    $text = 'Hallo %1$s, wollen uns in %2$s mal wieder treffen?';  
    printf ($text, 'Max Mustermann', 'Musterstadt');
    

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
    1. Hi!

      $text = 'Hallo %1$s, wollen uns in %2$s mal wieder treffen?';

      printf ($text, 'Max Mustermann', 'Musterstadt');

        
      Bei Datenhaltung in einem Array käme eher v(s)printf() in Frage.  
        
        
      Lo!
      
      1. Danke für eure Hinweise.

        An sprintf() hatte ich vorher auch gedacht, jedoch dürfte für einen zukünftiger Autor diese Schreibweise der Platzhalter unverständlich sein und er kennt ja auch nicht die Positionen der Ersetzungsvariablen. Es sollte daher schon beim erstellen des Textes erkennbar sein, wo eine spätere Ersetzung erfolgt und auch was sie enthalten wird. Daher ziehe ich %NAME% gegenüber %1$s eindeutig vor!

        Was sind jeweils die Vor- und Nachteile von preg_replace() vs. str_replace()?

        @dedlfix

        Du brauchst keine regulären Ausdrücke für solch simple Ersetzungen, str_replace() tut's auch. Damit oder besser mit strtr() in der zweiten Variante kannst du es unter Umständen auch noch eine weiter vereinfachen. Die Begrenzungszeichen müssten dann aber mit in den Suchtext geschrieben werden und nicht erst beim Ersetzen hinzugefügt werden. Aber auch preg_replace() kann Arrays als Parameter übernehmen, so dass das Interieren zu Fuß entfallen kann.

        Wie meinst du das genau? könntest du es bitte anhand meines Beispiel kurz erläutern!?

        1. Danke für eure Hinweise.

          An sprintf() hatte ich vorher auch gedacht, jedoch dürfte für einen zukünftiger Autor diese Schreibweise der Platzhalter unverständlich sein und er kennt ja auch nicht die Positionen der Ersetzungsvariablen. Es sollte daher schon beim erstellen des Textes erkennbar sein, wo eine spätere Ersetzung erfolgt und auch was sie enthalten wird. Daher ziehe ich %NAME% gegenüber %1$s eindeutig vor!

          Was sind jeweils die Vor- und Nachteile von preg_replace() vs. str_replace()?

          preg_replace() ist im Vergleich zu Stringfunktionen sehr träge und unhandlich. Zudem, wenn du ohnehin eine exakte Kette finden willst und nicht ein Muster, ist ein regulärer Ausdruck einfach unnötig.

          str_replace() wäre ebenfalls eine Möglichkeit, hier kannst du als Argumente Arrays angeben - dennoch ist sprintf hier das Mittel der Wahl, schlichtwe weil es die größtmögliche Übersichtlichkeit für dein Vorhaben zur Verfügung stellt.

          Ob du nun aber sprintf() oder str_replace() nimmst, ist imho hübsch egal - die dafür gedachte Variante ist aber eindeutig sprintf().

          Wie meinst du das genau? könntest du es bitte anhand meines Beispiel kurz erläutern!?

          Annahme du willst

          %suche1%, %suche12% oder %suche127% bzw. irgend eine weitere Möglichkeit mit einer belieben Zahl oder Zeichenkette (die du jeweils nicht kennst) hinten daran ersetzen, dann bist du mit Stringfunktionen schlecht bedient, es wird unötig kompliziert.

          Reguläre Ausdrücke kommen dann ins Spiel, wenn dir zwar das Muster aber nicht die exakte Zeichenkette bekannt ist.

          Also z.B. "Ersetze mir alle Zeichenketten die wie eine Hexadezimalzahl aussehen"

          Solche Mustererkennung bzw. die PCRE-Engine kostet aber Rechnenzeit - in den meisten Fällen wo es um kurze Texte geht ist es wahrscheinlich egal, aber bei langen Würsten gibt es teilweise beträchtliche Unterschiede die dann auch spürbar werden.

          1. str_replace() wäre ebenfalls eine Möglichkeit, hier kannst du als Argumente Arrays angeben - dennoch ist sprintf hier das Mittel der Wahl, schlichtwe weil es die größtmögliche Übersichtlichkeit für dein Vorhaben zur Verfügung stellt.

            Nachtrag: das war natürlich Blödsinn - das Mittel der Wahl ist str_replace() wenn dir die Reihenfolge unbekannt ist und du benannte Platzhalter willst.

            1. Ok Danke.

              Hab es jetzt so:
              str_ireplace("%" . $search . "%", $replace, $temp);

              Hat den Vorteil, das ein Platzhalter z.B. %NAME% und dessen Funktion eindeutig erkennbar und bei den Schlüsselworten Groß- Kleinschreibung egal ist.

              Gruß
              LBS

        2. @@LastBoyScout:

          nuqneH

          An sprintf() hatte ich vorher auch gedacht,

          Guter Gedanke. Verfolge ihn weiter!

          jedoch dürfte für einen zukünftiger Autor diese Schreibweise der Platzhalter unverständlich sein

          Ein PHP-Entwickler sollte PHP verstehen. Oder zumindestens die Doku kennen.

          und er kennt ja auch nicht die Positionen der Ersetzungsvariablen.

          Frei nach ChrisB: Wenn irgendwessen Gedanken gestützt werden müssen, heißt die Krücke dafür „Kommentar“, nicht „unsinniger Code“.

          $text = 'Hallo %1$s, wollen uns in %2$s mal wieder treffen?'; // %1$s: Name, %2$s: Ort  
          
          

          Qapla'

          --
          Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
          (Mark Twain)
          1. @Gunnar Bittersmann

            An sprintf() hatte ich vorher auch gedacht,

            Guter Gedanke. Verfolge ihn weiter!

            Für diesen Verwendungszweck jedoch leider absolut ungeeignet!!

            jedoch dürfte für einen zukünftiger Autor diese Schreibweise der Platzhalter unverständlich sein

            Ein PHP-Entwickler sollte PHP verstehen. Oder zumindestens die Doku kennen.

            Ich habe bewusst nicht von einem PHP-Entwickler gesprochen, sondern von einem Autor!
            Der unterschied ist klar: Ein Entwickler schreibt das Script und kennt somit die Variablen usw. Ein Autor benutzt das Script und Schreibt damit seinen Text welcher in der Variablen $text weiterverarbeitet wird. Der Autor hat keine Ahnung was im Hintergrund ab geht, kann aber anhand einer kurzen Doku erfahren, das %NAME% ein möglicher Platzhalter ist und jeweils durch einen Namen ersetzt wird. Hingegen wird man ihm %1$s nur sehr schwer erklären können, ist es doch Positionsabhängig und dadurch nicht eindeutig!

            und er kennt ja auch nicht die Positionen der Ersetzungsvariablen.

            Frei nach ChrisB: Wenn irgendwessen Gedanken gestützt werden müssen, heißt die Krücke dafür „Kommentar“, nicht „unsinniger Code“.

            $text = 'Hallo %1$s, wollen uns in %2$s mal wieder treffen?'; // %1$s: Name, %2$s: Ort

              
            Wie schon erwähnt kommt der Inhalt von `$text`{:.language-php} vom Benutzer und ist nicht festzementiert sondern dynamisch. Da nützt auch kein noch so guter Kommentar, den ein Benutzer eh nie zu Gesicht bekommt.  
              
            Wer sich die Aufgabenstellung genau durchliest und etwas weiter denkt wird den Unterschied bemerken.
            
            1. @@LastBoyScout:

              nuqneH

              Ich habe bewusst nicht von einem PHP-Entwickler gesprochen, sondern von einem Autor!

              Na wenn das so ist, sollte der Autor wohl überhaupt keinen PHP-Code zu Gesicht bekommen, sondern ein CMS.

              Qapla'

              --
              Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
              (Mark Twain)
              1. @

                Na wenn das so ist, sollte der Autor wohl überhaupt keinen PHP-Code zu Gesicht bekommen, sondern ein CMS.

                Eben, er bekommt ein Formularfeld zu sehen, in welches er seinen Text samt der Platzhalter für die nachfolgende Ersetzung und Weiterverarbeitung eingeben kann:

                <textarea cols=\"80\" rows=\"10\" name=\"text\">Hallo %NAME%, wollen wir uns in %Ort% mal wieder treffen? etc...</textarea>

                Eventuell bastele ich auch noch ein JavaScript zum einfügen der korrekten Platzhalter!?

                Gruß
                LBS

    2. $text = 'Hallo %1$s, wollen uns in %2$s mal wieder treffen?';

      printf ($text, 'Max Mustermann', 'Musterstadt');

        
      sprintf() ist eine alternative, im Gegensatz zu printf() wird der String nicht sofort ausgegeben sondern kann in eine Variable gespeichert werden.
      
  2. Hi!

    $temp = preg_replace("/%" . $search . "%/", $replace, $temp);
    Es funktioniert soweit auch ganz gut, nur denke ich das ich es bestimmt etwas umständlich gemacht habe und es mit Sicherheit eleganter bzw. einfacher gelöst werden könnte?

    Du brauchst keine regulären Ausdrücke für solch simple Ersetzungen, str_replace() tut's auch. Damit oder besser mit strtr() in der zweiten Variante kannst du es unter Umständen auch noch eine weiter vereinfachen. Die Begrenzungszeichen müssten dann aber mit in den Suchtext geschrieben werden und nicht erst beim Ersetzen hinzugefügt werden. Aber auch preg_replace() kann Arrays als Parameter übernehmen, so dass das Interieren zu Fuß entfallen kann.

    Und weil du schon "mit Sicherheit" erwähnst, "unter Umständen" schrieb ich deshalb, weil diese Form nur ohne Beachtung eines eventuellen Kontextwechsels verwendet werden kann. Wenn dieser in deinem Fall relevant ist, solltest du doch zu Fuß iterieren und str_replace() mit einzelnen Strings verwenden.

    Der Kontextwechsel wäre auch in deinem Code zu beachten gewesen, nämlich für $search, das du ohne Inhaltsbetrachtung in den regulären Ausdruck einfügst. Darin könnten für das Suchmuster relevante Zeichen enthalten sein, wenn du das nicht anderweitig konsequent ausschließen kann.

    Lo!

  3. Wenn es denn unbedingt mit preg-Funktionen gelöst werden soll, dann schau dir doch mal das an:
    <http://www.phpro.org/tutorials/Introduction-to-PHP-Regex.html#9

    Gruß,

    --
    Science flies you to the moon.
    Religion flies you into buildings.
    selfcode: ie:{ fl:| br:^ va:? ls:< fo:{ rl:( n4:{ ss:} de:[ js:} ch:{ sh:) mo:? zu:)