Willi H.: Platzhalter in Strings

Guten Tag!

Könnte mir bitte jemand den Unterschied zwischen folgenden beiden Varianten erklären?

<?php echo sprintf('Hallo %s, meine Name ist %s.', $deinName, $meinName); ?>

<?php echo sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName); ?>

Schöne Grüße vom Willi

  1. Hi,

    Könnte mir bitte jemand den Unterschied zwischen folgenden beiden Varianten erklären?

    <?php echo sprintf('Hallo %s, meine Name ist %s.', $deinName, $meinName); ?>

    <?php echo sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName); ?>

    Das Handbuch kann: http://www.php.net/manual/en/function.sprintf.php

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Guten Tag, ChrisB!

      Das Handbuch kann: http://www.php.net/manual/en/function.sprintf.php

      Danke sehr! Die zweite Variante ist demnach nur dann relevant, wenn die Reihenfolge der Variablen nicht der Reihenfolge der Platzhalter entspricht.

      In meinem Beispiel spielt es also keine Rolle, welche der beiden Platzhalter-Varianten verwendet werden, in folgender abgewandelter Version hingegen schon.

      <?php echo sprintf('Hallo %2$s, mein Name ist %1$s.', $meinName, $deinName); ?>

      Habe ich das so richtig zusammengefasst?

      Schöne Grüße vom Willi

      1. Hi,

        In meinem Beispiel spielt es also keine Rolle, welche der beiden Platzhalter-Varianten verwendet werden, in folgender abgewandelter Version hingegen schon.

        <?php echo sprintf('Hallo %2$s, mein Name ist %1$s.', $meinName, $deinName); ?>

        Habe ich das so richtig zusammengefasst?

        Ja, genau.
        Und wie im Manual auch steht, ist das bspw. praktisch, wenn man Internationalisierung betreiben will, und dabei andere Satzstrukturen in anderen Sprachen berücksichtigen muss - damit kann man die Platzierung von Werten innerhalb der Ausgabe simpel im Formatstring anpassen, ohne die Reihenfolge der Funktionsparameter ändern zu müssen.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Guten Tag, ChrisB!

          Ja, genau.
          Und wie im Manual auch steht, ist das bspw. praktisch, wenn man Internationalisierung betreiben will, und dabei andere Satzstrukturen in anderen Sprachen berücksichtigen muss - damit kann man die Platzierung von Werten innerhalb der Ausgabe simpel im Formatstring anpassen, ohne die Reihenfolge der Funktionsparameter ändern zu müssen.

          Ausgezeichnet. Danke für die Hilfe!

          Schöne Grüße vom Willi

        2. @@ChrisB:

          nuqneH

          Und wie im Manual auch steht, ist das bspw. praktisch, wenn man Internationalisierung betreiben will, und dabei andere Satzstrukturen in anderen Sprachen berücksichtigen muss - damit kann man die Platzierung von Werten innerhalb der Ausgabe simpel im Formatstring anpassen, ohne die Reihenfolge der Funktionsparameter ändern zu müssen.

          Was man meist gar nicht tun kann, denn man möchte ja die Programmlogik für alle Sprachen dieselbe sein, man möchte da nichts mehrfach implementieren.

          Und die Strings kommen of aus einer Datenbank (was eine Datei sein kann, nicht unbedingt ein DBMS), bspw;

          $message = Array(  
            'de' => 'Datei %2$s enthält %1$d Rechtschreibfehler.',  
            'en' => 'There were %1$d spelling mistakes in file %2$s.',  
          );
          

          Irgenwo ist dann $lang = 'de'; gesetzt, irgendwo anders werden $spellerrors und $filename mit Werten befüllt.

          Zur Ausgabe heißt es dann <p><?php [code lang=php]printf($message[$lang], $spellerrors, $filename); ?></p>[/code]

          Ohne '%1$d' und '%2$s' ginge das gar nicht.

          s.a. Working with Composite Messages > Variables that cannot be reordered.

          Oops, denen sind die $$ ausgegangen.

          Qapla'

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

        Habe ich das so richtig zusammengefasst?

        <?php echo sprintf($TextMitPlatzhalternDerSichAendernKann, $meinName, $deinName); ?>

        Häufig wird der Text nicht direkt als Literal übergeben, sondern in einer Variable gespeichert und vielleicht auch häufiger verwendet. Unter Umständen willst du diesen dann später ändern. Dabei kann es sein, dass du die an sprintf übergebenen Parameter in einer anderen Reihenfolge ausgeben willst. Dann ist es schon von Vorteil, wenn man nicht jedes mal die Reihenfolge der Parameter ändern muss.

        Viele Grüße Novi

        --
        "(...) deshalb mag ich Binärtechnik. Da gibt es nur drei Zustände: High, Low und Kaputt." (Wau Holland)
        1. Guten Tag, Novi!

          <?php echo sprintf($TextMitPlatzhalternDerSichAendernKann, $meinName, $deinName); ?>

          Häufig wird der Text nicht direkt als Literal übergeben, sondern in einer Variable gespeichert und vielleicht auch häufiger verwendet. Unter Umständen willst du diesen dann später ändern. Dabei kann es sein, dass du die an sprintf übergebenen Parameter in einer anderen Reihenfolge ausgeben willst. Dann ist es schon von Vorteil, wenn man nicht jedes mal die Reihenfolge der Parameter ändern muss.

          Das ist plausible. Danke auch dir für deine Hilfe!

          Schöne Grüße vom Willi

      3. Hello,

        Das Handbuch kann: http://www.php.net/manual/en/function.sprintf.php

        Danke sehr! Die zweite Variante ist demnach nur dann relevant, wenn die Reihenfolge der Variablen nicht der Reihenfolge der Platzhalter entspricht.

        In meinem Beispiel spielt es also keine Rolle, welche der beiden Platzhalter-Varianten verwendet werden, in folgender abgewandelter Version hingegen schon.

        <?php echo sprintf('Hallo %2$s, mein Name ist %1$s.', $meinName, $deinName); ?>

        Habe ich das so richtig zusammengefasst?

        Du könntest dir mal in einer Compiler-Hochsprache, die diese Syntax benutzt (also vermutlich C) den erzeugten Assembler-Code anschauen. Dann wirst Du sehen, dass im Anwendungsfall mit

        sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName);

        der getriebene Aufwand schon erheblich höher ist. Das macht einen dann schon nachdenklich, wenn man sich um Sinn und Unsinn in Programmiersprachen überhaupt noch interessiert.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Guten Abend, Tom vom Berg!

          Du könntest dir mal in einer Compiler-Hochsprache, die diese Syntax benutzt (also vermutlich C) den erzeugten Assembler-Code anschauen. Dann wirst Du sehen, dass im Anwendungsfall mit

          sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName);

          der getriebene Aufwand schon erheblich höher ist. Das macht einen dann schon nachdenklich, wenn man sich um Sinn und Unsinn in Programmiersprachen überhaupt noch interessiert.

          Also vermeiden, wo es möglich ist?

          Schöne Grüße vom Willi

          1. Lieber Willi H.,

            sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName);
            der getriebene Aufwand schon erheblich höher ist. Das macht einen dann schon nachdenklich, wenn man sich um Sinn und Unsinn in Programmiersprachen überhaupt noch interessiert.

            Also vermeiden, wo es möglich ist?

            machst Du Dir Gedanken über Sinn und Unsinn? Wenn nicht, dann brauchst Du es nicht vermeiden.

            Sieh es einmal so: Wenn die Reihenfolge Deiner Parameter mit der Reihenfolge der ihnen zugedachten Platzhalter übereinstimmt, dann machst Du das mit "%s" bzw. "%d". Das wird wohl in den allermeisten Fällen so sein.

            Solltest Du Dein Script für mehrere Sprachen bauen, sodass die zusammen zu bauenden Strings die Parameter in verschiedener Reihenfolge brauchen könnten, dann benutzt Du eben "%1$s" bzw. "%1$d". Beispiel:

            $message = array(  
                'de' => 'Heute ist %1$s, der %3$d. %2$s %4$d.',  
                'en' => 'Today\'s date: %1$s, %2$d %3$s %4$d'  
            );  
            $out = sprintf($message[$lang], $weekday[$lang], $month[$lang], $day, $year);
            

            Ich benutze in fast allen Fällen "%s" und "%d", nur dann, wenn ich einen Parameter mehrfach im String einfügen möchte, dann benutze ich "%1$s". Beispiel: $xml = sprintf('<%1$s>%2$s</%1$s>', $tagName, $data);

            Liebe Grüße,

            Felix Riesterer.

            --
            ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
            1. @@Felix Riesterer:

              nuqneH

              Sieh es einmal so: Wenn die Reihenfolge Deiner Parameter mit der Reihenfolge der ihnen zugedachten Platzhalter übereinstimmt, dann machst Du das mit "%s" bzw. "%d". Das wird wohl in den allermeisten Fällen so sein.

              Nein, damit schließt man bei der Implementation der Logik eine spätere Lokalisierung der Website aus oder erschwert sie zumindest. Und das völlig unnötigerweise.

              Der Rat kann nur sein, '%1$s' und '%2$d' zu verwenden. Von Anfang an, um sich alle Optionen für später offenzuhalten.

              Ich zitiere Addison Phillips: “Internationalization is not a feature. It is an architecture.”

              Qapla'

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

                nuqneH

                […] um sich alle Optionen für später offenzuhalten.

                BTW, zu den Optionen gehört auch eine mögliche Umformulierung des (deutschen?) Originaltextes.

                Man muss gar nicht in die Ferne schweifen …

                Qapla'

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

                Sieh es einmal so: Wenn die Reihenfolge Deiner Parameter mit der Reihenfolge der ihnen zugedachten Platzhalter übereinstimmt, dann machst Du das mit "%s" bzw. "%d". Das wird wohl in den allermeisten Fällen so sein.

                Nein, damit schließt man bei der Implementation der Logik eine spätere Lokalisierung der Website aus oder erschwert sie zumindest. Und das völlig unnötigerweise.

                Der Rat kann nur sein, '%1$s' und '%2$d' zu verwenden. Von Anfang an, um sich alle Optionen für später offenzuhalten.

                Gerade wenn die Format-Strings separat abgelegt werden, wie du das selber angedeutet hast, sehe ich das Problem nicht - *wenn* ich die Parameter mal in einer Formatierung in anderer Reihenfolge brauche, dann kann ich doch in *diesem* Formatstring die nummerierte Variante immer noch problemlos wählen.

                MfG ChrisB

                --
                RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
                1. @@ChrisB:

                  nuqneH

                  Gerade wenn die Format-Strings separat abgelegt werden, wie du das selber angedeutet hast, sehe ich das Problem nicht - *wenn* ich die Parameter mal in einer Formatierung in anderer Reihenfolge brauche, dann kann ich doch in *diesem* Formatstring die nummerierte Variante immer noch problemlos wählen.

                  Hm, gemischte Verwendung. Möglich, ja. Aber der Weisheit letzter Schluss ist das wohl nicht.

                  Es ist bei der Lokalisierung ein Leichtes,
                  'There were %1$d spelling mistakes in file %2$s.'
                  in
                  'Datei %2$s enthält %1$d Rechtschreibfehler.'
                  zu übersetzen.

                  Heißt es hinggen original
                  'There were %d spelling mistakes in file %s.'
                  würde ein Übersetzer (der nicht zwangsläufig weitreichende PHP-Kenntnisse haben muss), daraus womöglich
                  'Datei %s enthält %d Rechtschreibfehler.'
                  machen.

                  i18n fail. Man sollte Übersetzern nicht die Chance geben, solche Fehler zu machen. Ich halte meinen Einwand gegen '%s' und '%d' aufrecht.

                  Qapla'

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

                    Heißt es hinggen original
                    'There were %d spelling mistakes in file %s.'
                    würde ein Übersetzer (der nicht zwangsläufig weitreichende PHP-Kenntnisse haben muss), daraus womöglich
                    'Datei %s enthält %d Rechtschreibfehler.'
                    machen.

                    Gut, das kann ich als Argument gelten lassen.

                    Man sollte Übersetzern nicht die Chance geben, solche Fehler zu machen.

                    Wobei generelle Rücksichtnahme auf „den sie wissen nicht, was sie tun“ für mich eigentlich weniger ein stichhaltiges Argument ist.
                    Man kann dokumentieren, man kann Mitarbeiter schulen.

                    MfG ChrisB

                    --
                    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
                    1. @@ChrisB:

                      nuqneH

                      Man sollte Übersetzern nicht die Chance geben, solche Fehler zu machen.

                      Wobei generelle Rücksichtnahme auf „den sie wissen nicht, was sie tun“ für mich eigentlich weniger ein stichhaltiges Argument ist.
                      Man kann dokumentieren, man kann Mitarbeiter schulen.

                      Not their job.

                      Einem Übersetzer mag es zuzumuten sein, in

                      $message = Array(  
                        'en' => 'There were %1$d spelling mistakes in file %2$s.',  
                      );
                      

                      die Zeile
                      'de' => 'Datei %2$s enthält %1$d Rechtschreibfehler.',
                      richtig einzufügen.

                      Es ist ihm aber nicht zuzumuten, dass er, wenn er

                      $message = Array(  
                        'en' => 'There were %d spelling mistakes in file %s.',  
                      );
                      

                      vorgesetzt bekommt, inder Übersetzung '%d' und '%s' umwandelt in '%1$d' bzw. '%2$s'.

                      Wenn nach der Übersetzung nochmal Entwickler ran müssten, dann hieße das, dass die Entwickler vorher Pfusch abgeliefert haben.

                      Qapla'

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

            Du könntest dir mal in einer Compiler-Hochsprache, die diese Syntax benutzt (also vermutlich C) den erzeugten Assembler-Code anschauen. Dann wirst Du sehen, dass im Anwendungsfall mit

            sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName);

            der getriebene Aufwand schon erheblich höher ist. Das macht einen dann schon nachdenklich, wenn man sich um Sinn und Unsinn in Programmiersprachen überhaupt noch interessiert.

            Also vermeiden, wo es möglich ist?

            Das kann man mMn nicht pauschal sein. Dazu müsste man wissen, ob Dein Programm noch eine andere Möglichkeit der Parameterzuordnung besitzt.

            Diese Variante von sprintf() stellt quasi eine Schnittstelle dar, die in der Hochsprache eingebaut ist. Die Position der Daten wird von der Position in der Ausgabe entkoppelt.

            In der OOP treibt man diesen Aufwand i.d.R. ohnenhin (bei echten Stringklassen sowieso), sodass Du kaum noch Gelegenheit zur "Optimierung" hättest und darüber gar nicht mehr nachdenkst.

            Was PHP als Interpreter nun wieder daraus macht, steht noch auf einem ganz anderen Blatt.

            Ich stehe aber auf dem Standpunkt, dass man aus der nativen Hochsprache (in der die Interpretersprache geschrieben wurde) ausgeliehene oder "durchgereichte" Funktionen in einer Interpretersprache sowieso nicht unbedacht benutzen sollte, da sie die "Sprachmelodie" der Interpretersprache i.d.R. missachten. Es wäre in PHP konsequent, die Fragmente des Ausgabestrings in der Datenhaltung des Scriptes in einem Array zu speichern, und dann dessen Elemente ausgeben zu lassen, selbstverständlich (einzeln oder gesamt) behandelt mit der passenden Kontextmethode!

            Hier fehlt aber sicherlich auch noch ein "printarray()" oder "toString()" für Arrays in PHP.

            Arrays konsequent anzuwenden ergibt dann freilich in der Maschinencodeebene normalerweise noch mehr Overhead. Aber dann dient dieser zumindest in der Sprachebene des Projektes der glasklaren Sprachreinheit.

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
        2. Tach.

          Du könntest dir mal in einer Compiler-Hochsprache, die diese Syntax benutzt (also vermutlich C) den erzeugten Assembler-Code anschauen. Dann wirst Du sehen, dass im Anwendungsfall mit

          sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName);

          der getriebene Aufwand schon erheblich höher ist. Das macht einen dann schon nachdenklich, wenn man sich um Sinn und Unsinn in Programmiersprachen überhaupt noch interessiert.

          Ich verstehe den Zusammenhang nicht. Um welchen Sinn oder Unsinn geht es und was hat das mit Assembler zu tun?

          --
          Always remember that you are unique. Just like everybody else.
  2. Hallo,

    <?php echo sprintf('Hallo %s, meine Name ist %s.', $deinName, $meinName); ?>

    <?php echo sprintf('Hallo %1$s, meine Name ist %2$s.', $deinName, $meinName); ?>

    Schöne Grüße vom Willi

    Hier musste die Reihenfolge der Variablen ändern:
    <?php echo sprintf('Meine Name ist %s. Hallo %s', $meinName, $deinName); ?>

    Hier nicht:
    <?php echo sprintf('Meine Name ist %2$s. Hallo %1$s', $deinName, $meinName); ?>

    Viele Grüße Novi

    --
    "(...) deshalb mag ich Binärtechnik. Da gibt es nur drei Zustände: High, Low und Kaputt." (Wau Holland)
    1. Guten Tag, Novi!

      Hier musste die Reihenfolge der Variablen ändern:
      <?php echo sprintf('Mein Name ist %s. Hallo %s', $meinName, $deinName); ?>

      Du meintest sicherlich, dass ich hier die Reihenfolge ändern müsste:
      <?php echo sprintf('Mein Name ist %s. Hallo %s', $deinName, $meinName); ?>

      Hier nicht:
      <?php echo sprintf('Mein Name ist %2$s. Hallo %1$s', $deinName, $meinName); ?>

      Schöne Grüße vom Willi

      1. Hallo,

        eigentlich meinte ich mit "musste" "musst du" und das Code-Beispiel zeigt dabei schon die erfolgte Änderung der Reihenfolge an.

        Viele Grüße Novi

        --
        "(...) deshalb mag ich Binärtechnik. Da gibt es nur drei Zustände: High, Low und Kaputt." (Wau Holland)
        1. Guten Abend, Novi!

          eigentlich meinte ich mit "musste" "musst du"

          Das hatte ich auch so verstanden.

          und das Code-Beispiel zeigt dabei schon die erfolgte Änderung der Reihenfolge an.

          Ach sooo war das gemeint.

          Schöne Grüße vom Willi