Wird es als schlechte Praxis angesehen, PHP in Ihrem JavaScript zu haben?

55

So oft sehe ich auf dieser Seite Leute, die versuchen, Dinge wie diese zu tun:

<script type="text/javascript">
  $(document).ready(function(){

     $('<?php echo $divID ?>').click(funtion(){
       alert('do something');
     });

  });
</script>

Ich denke nicht, dass dies eine Art Muster ist, in das die Leute auf natürliche Weise verfallen. Es muss eine Art Tutorial oder Lernmaterial geben, das dies zeigt, sonst würden wir es nicht so oft sehen. Was ich frage ist, mache ich zu viel daraus oder ist das eine wirklich schlechte Praxis?

EDIT: Ich habe mit einem Freund darüber gesprochen, der oft Rubin in sein JavaScript eingibt, und er hat diesen Punkt angesprochen.

Ist es in Ordnung, anwendungsweite Konstanten dynamisch in Ihrem JavaScript zu platzieren, damit Sie nicht zwei Dateien bearbeiten müssen? zum Beispiel...

MYAPP.constants = <php echo json_encode($constants) ?>;

Ist es auch in Ordnung, Daten, die Sie in einer Bibliothek verwenden möchten, direkt zu codieren?

ChartLibrary.datapoints = <php echo json_encode($chartData) ?>;   

oder sollten wir jedes Mal einen AJAX-Anruf tätigen?

Greg Guida
quelle
4
Es scheint mir, dass this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom
7
@ M.Babcock Dies wäre Teil einer .php-Datei, so dass PHP-Code serverseitig ausgeführt wird und der Client nur das Ergebnis des Echos sieht.
8
Wer dynamisch generiertes JavaScript erstellt, wird zurückgenommen und behandelt
Raynos 22.12.11
5
@ Matt, dann gehe ich zurück zu Google und kümmere mich um sie
Raynos
4
"Du hast dein Javascript in meinem PHP!" "Nein, du hast dein PHP in meinem Javascript!"
Josh Darnell

Antworten:

83

Normalerweise es ist eine schlechte Praxis Sprache X zu verwenden , um Code in Sprache Y. zu erzeugen

Versuchen Sie, die beiden Sprachen zu entkoppeln, indem Sie Daten zur einzigen Schnittstelle machen - mischen Sie den Code nicht .

In Ihrem Beispiel können Sie den Code verbessern, indem Sie mit PHP eine cfgStruktur auffüllen, die für JavaScript verfügbar ist:

<script type="text/javascript">
  var cfg = {
    theId: "<?php echo $divID ?>",
    ...
  };

  $(document).ready(function(){
     $("#" + cfg.theId).click(funtion(){
       alert('do something');
     });
  });
</script>

Auf diese Weise kümmert sich PHP nur darum, die Datenstruktur zu füllen, und JavaScript kümmert sich nur darum, die Datenstruktur zu konsumieren.

Diese Entkopplung führt auch zum zukünftigen asynchronen Laden der Daten (JSON).

Aktualisieren:

Um die zusätzlichen Fragen zu beantworten, die Sie mit Ihrem Update gestellt haben, ist es empfehlenswert, das DRY-Prinzip anzuwenden und PHP und JavaScript dasselbe Konfigurationsobjekt zuzulassen:

<script type="text/javascript">
  var cfg = <?php echo json_encode($cfg) ?>;

  ...

Es schadet nicht, die JSON-Darstellung Ihrer Konfiguration direkt in Ihre Seite einzufügen. Sie müssen es nicht unbedingt über XHR abrufen.

Ates Goral
quelle
21
Denken Sie jedoch daran, Ihr MySQL-Passwort nicht in $ cfg einzutragen !!
Thomas Bonini
13
"Daten zur einzigen Schnittstelle machen - Code nicht mischen." Ich denke, dass dies wirklich zum Kern des Problems führt und eine gute Faustregel ist, wenn Sie ALLE zwei Sprachen zusammen verwenden. Danke für den Einblick.
Greg Guida
6
Sie können diese JSON auch in ein data-Attribut in Ihrem HTML-Code einfügen. So etwas wie <body data-cfg="{...}">.
Kapa
1
@bazmegakapa Ich denke, das könnte die beste Option sein. Insbesondere können APIs wie HTML DOM verwendet werden, die das Risiko von XSS-Injektionen erheblich verringern.
Luiscubal
1
+1 für den Vorschlag, Daten als Schnittstelle zu verwenden und Code zu entmutigen, der Code generiert.
Brandon
21

Dynamisch generiertes JavaScript ist eine schreckliche, schlechte Praxis.

Was Sie tun sollen, ist zu verstehen, was Trennung von Bedenken und fortschreitende Verbesserung bedeutet.

Dies bedeutet im Grunde, dass Sie dynamisches HTML und statisches JavaScript verwenden (wodurch das HTML verbessert wird).

In Ihrem Fall möchten Sie wahrscheinlich eine Klasse in Ihrem div und wählen Sie sie mit einem Klassen-Selektor aus

Raynos
quelle
10

Das größte Problem mit deinem Snippet ist, dass du das verpasst #, um es zu einem gültigen jQuery-Selektor zu machen;).

Ich würde sagen, Sie sollten es nach Möglichkeit vermeiden, PHP in Ihr JavaScript aufzunehmen. Was ist falsch daran, den Selektor in Ihrem click()Handler in eine Klasse zu ändern und die Klasse dem betreffenden Element hinzuzufügen, wenn der Handler ausgelöst werden soll, und nicht, wenn dies nicht der Fall ist?

<script type="text/javascript">
  $(document).ready(function(){

     $('.foo').click(funtion(){
       alert('do something');
     });

  });
</script> 

<div id="bar" class="<?php echo ($someCond ? 'foo' : ''); ?>">Hello</div>

Es gibt Situationen , in denen Sie benötigen PHP in Ihrem JavaScript aufzunehmen; aber ich muss zugeben, das sind nur wenige und weit voneinander entfernt.

Ein Beispiel ist, wenn Sie unterschiedliche Umgebungen haben. testen, inszenieren und leben. Jeder von ihnen hat einen anderen Ort für Ihr Vermögen (hauptsächlich Bilder). Der einfachste Weg, um den Pfad so einzustellen, dass er von JavaScript verwendet werden kann, ist so etwas wie;

var config = { assets: "<?php echo $yourConfig['asset_url']; ?>" };
Matt
quelle
Im Rest meines imaginären PHP-Codes habe ich bereits das #=) angehängt, aber im Ernst, ich stimme zu, dass Ihr Beispiel der bessere Weg ist, dies zu tun. Es erscheint mir natürlicher, es auch so zu machen. Warum sehen wir es dann so oft an Orten, an denen es nicht notwendig ist?
Greg Guida
Beachten Sie, dass das Echo statischer Daten in einer Konfigurationsdatei leicht vermieden werden kann, wenn alle Umgebungen auf die gleiche Weise eingerichtet werden.
Raynos
4
@GregGuida: Ich denke, Programmierer sind es selten gewohnt, mit Client / Server-Architekturen umzugehen, wie man sie in der Webentwicklung kennt. Sie behandeln DB <-> PHP <-> HTML / JS / CSS als eine, und nicht vollständig verstehen , was sollte gehen , wo und wie die Schichten getrennt werden sollten.
Matt
@ Matt Ich denke, das ist wahrscheinlich die beste Erklärung
Greg Guida
2
$divID = '#' . $element_id_value;- keine probleme mit dem selector boss;)
rlemon 22.12.11
8

Dies ist meiner Meinung nach eine schlechte Praxis, da Sie diese Datei "something.php" aufrufen müssten und sie dann beispielsweise nicht komprimieren könnten. Ganz zu schweigen davon, dass es nicht in Ordnung ist, Ihre Server-Inhalte mit Ihrem JavaScript zu mischen. Versuchen Sie, das Mischen zwischen PHP und JS so weit wie möglich zu begrenzen.

Sie können dies stattdessen jederzeit tun:

function setOnClick(divid) {
 $(divid).click(funtion(){
   alert('do something');
 });
}

Und dann könnten Sie diese Funktion in einer PHP-Datei aufrufen, um diese Mixing-Dinge so klein wie möglich zu machen.

$(function() {
  setOnClick('<?php echo $divId; ?>');
});

Auf diese Weise (mit größeren JS-Dateien, nicht 2-3 Zeilen, wo es egal ist) können Sie die JS-Datei komprimieren, und Front-End-Entwickler fühlen sich meiner Meinung nach sehr wohl, wenn sie nur mit JavaScript arbeiten (wie Sie schreiben könnten) Python, Ruby usw., nicht nur PHP - und der Code könnte immer größer werden, je nachdem, was Sie dort tun müssen.

alessioalex
quelle
2
Völlig einverstanden, übrigens habe ich nie PHP in meinem JS. Ich sehe es die ganze Zeit auf dieser Seite.
Greg Guida
Der PHP-Code schafft es nie zum Browser! Nur der ausgewertete Code, der jetzt klares Javascript sein sollte. Daher ist Dateigröße / Komprimierung kein Problem. Noch schlechte Praxis gedacht!
James Anderson
@ James Anderson Ich denke, alessioalex bezieht sich auf die Verkleinerung (wie Uglify). Es kann möglich sein, das PHP laufen zu lassen und dann die Antwort von einer Nachbearbeitungs-PHP-Funktion analysieren zu lassen, das Skript-Tag zu identifizieren, es über Uglify auszuführen und das ursprünglich vom PHP erzeugte JS durch die verkleinerte Version zu ersetzen, bevor die Antwort gesendet wird. aber das klingt auf jeden wunsch wie ein huch! Ansatz.
Jinglesthula
6

Ich denke nicht, dass dies eine schlechte Praxis ist. Wenn die in Ihrem JavaScript erforderliche ID dynamisch ist, gibt es keine andere Möglichkeit, dies zu tun.

CodeZombie
quelle
5
Warum in dem unheiligen Namen von Cuthulu würdest du den Namen eines ID-Tags nicht kennen?
Inkognito
3
@Incognito, es gibt viele Male, in denen Sie die ID nicht kennen ... Wenn Sie Ajax zum Generieren neuer Codeblöcke verwenden, generieren Sie möglicherweise eindeutige IDs zusammen mit neuem JS ... in diesen Fällen müssen Sie dies tun Stellen Sie sicher, dass die IDs, auf die verwiesen wird, in js und im resultierenden Codeblock identisch sind. Es gibt viel mehr Fälle wie diesen und es ist ziemlich häufig, wenn Ajax beteiligt ist oder es große Codeblöcke gibt, die von einer serverseitigen if-else-Anweisung usw. abhängen
7
@raynjamin Ich verstehe nicht einmal, wie Sie sich in Situationen versetzen, in denen Sie das tun ... oder warum Sie nach Klasse auswählen, dann Tags auflisten und dann ID-Attribute, die einen versteckten CSS-Wert haben, diesen Selektor ... es tut mir wirklich weh, mich umzusehen ... Ich weiß nicht einmal, wo ich anfangen soll ... wie ... was? Schneiden Sie große Codeblöcke aus und fügen Sie sie ein oder fügen Sie sie so ein, dass die Arbeit mit mehreren IDs funktioniert? Ich mag nicht einmal ... mein Gehirn. es explodiert hier.
Inkognito
3
Lesen Sie mehr über dom / html / whatever ... verwenden Sie eine Suchmaschine ... Warum musste ich noch nie so etwas mit dynamischem HTML machen?
Inkognito
5
Nein. Sie verstehen nicht, wie ID-Tags funktionieren. Ich verstehe genau, was du sagst.
Inkognito
6

Ich würde diese schlechte Praxis in Betracht ziehen. Wenn Sie dynamische Inhalte in Skriptblöcke einfügen, müssen Sie sich immer der Tatsache bewusst sein, dass das Entkommen in einem JavaScript-Kontext nicht so einfach ist, wie Sie es sich erhoffen. Wenn Werte vom Benutzer angegeben wurden, reicht es nicht aus, sie mit HTML zu maskieren.

Das OWASP XSS-Spickzettel enthält mehr Details, aber im Grunde sollten Sie dieses Muster übernehmen:

<script id="init_data" type="application/json">
    <?php echo htmlspecialchars(json_encode($yourdata)); ?>
</script>

Laden Sie dann in einer separaten .js-Datei, die mit Ihrem Haupt-HTML-Code verknüpft ist, diesen Code:

var dataElement = document.getElementById('init_data');
var jsonText = dataElement.textContent || dataElement.innerText  // unescapes the content of the span
var initData = JSON.parse(jsonText);

Es gibt zwei Gründe für die Verwendung einer separaten .js-Datei:

  • Es ist zwischenspeicherbar, damit die Leistung besser ist
  • Der HTML-Parser wird nicht ausgelöst, daher besteht nicht die Gefahr, dass ein XSS-Fehler dadurch überspringt, dass jemand irgendwo ein schnelles <? Php-Tag einfügt
Joeri Sebrechts
quelle
+1 zur vollständigen Erläuterung des XSS-Winkels! Ihr Ansatz wird schneller geladen, da der Json vor dem Domready geladen wird, aber ich bevorzuge das automatische Parsing von $.ajax
Json
5

Einige Leute würden argumentieren, dass es schlechte Praxis ist. Nicht, weil es sich um PHP in JS handelt, sondern weil es sich um Inline-JS handelt und daher nicht vom Browser zwischengespeichert wird, um das Laden beim nächsten Mal zu vereinfachen.

IMO ist es immer besser, JSON zu verwenden, um Variablen zwischen den beiden Sprachen zu übergeben, aber ich denke, es liegt an Ihnen.

Nick
quelle
5

Ich würde sagen, dass das im Allgemeinen nicht der Fall ist. Wenn Sie jedoch Daten von PHP -> Javascript übergeben möchten, wäre es für mich nicht verrückt, einen Inline-Javascript-Block zu haben, in dem Sie den Code des unten gezeigten Formulars haben. Hier übergibt der Code lediglich Daten von PHP an Javascript und erstellt keine Logik im laufenden Betrieb oder dergleichen. Der gute Teil dieses Vorgangs gegenüber einem Ajax-Aufruf besteht darin, dass die Daten verfügbar sind, sobald die Seite geladen wird, und keine zusätzliche Reise zum Server erforderlich ist.

<script>
window.config = <?php echo json_encode($config);?>;
</script>

Natürlich besteht eine andere Möglichkeit darin, eine Javascript-Konfigurationsdatei aus PHP über eine Art Erstellungsskript zu erstellen, das diese in eine .js-Datei schreibt.

Zachary K
quelle
4

Das Einzige, woran ich denken kann, was wirklich Probleme verursachen kann, ist, dass PHP-Fehler angezeigt werden und daher eine Menge HTML-Code in Ihr JavaScript geladen wird, der den PHP-Fehler anzeigt.

Auch weil es sich um ein Skript handelt, wird es daher nicht angezeigt und es kann manchmal eine Weile dauern, bis erkannt wird, warum Ihr Skript fehlerhaft ist.

Alex Coplan
quelle
Großartiger Fall, in dem dies einen großen Fehler verursacht
Greg Guida
3

Es kommt darauf an, von wem, und wenn Sie mich fragen, ja, ich halte es aus ein paar Gründen für üblich. Zuallererst würde ich es vorziehen, Javascript-Code in einer eigenen JS-Datei zu haben, die der PHP-Parser nicht anfassen kann.

Zweitens wird PHP nur zur Serverzeit ausgeführt. Wenn Sie also auf eine Variable in PHP angewiesen sind, um Ihr Javascript zu ändern, funktioniert dies möglicherweise nicht sehr gut. Wenn es eine Einstellung zum Laden von Seiten gibt, die Sie mit Javascript steuern möchten, ziehe ich es normalerweise vor, diesen Wert mit PHP zum DOM hinzuzufügen, damit Javascript darauf zugreifen kann, wann und wenn es möchte (zum Beispiel in einem versteckten Div).

Schließlich kann dies nur aus organisatorischen Gründen sehr ärgerlich werden. Es ist schon schlimm genug, HTML und PHP zu mischen (meiner Meinung nach).

Explosionspillen
quelle
1

Das Einbinden von PHP in ein configDatenobjekt reicht zu 90% aus, es empfiehlt sich jedoch, das Objekt vollständig zu trennen. Sie können eine RESTful-API verwenden, um nur die Daten anzufordern, die Sie benötigen. Es handelt sich um etwas mehr Javascript, aber mit einigen Vorteilen.

  • Skript ist statisch und kann permanent zwischengespeichert werden
  • PHP ist kein XSS-Vektor mehr
  • Vollständige Trennung von Bedenken

Nachteile:

  • Benötigt eine zusätzliche HTTP-Anfrage
  • komplexeres Javascript

Skript

//pure javascript
$.on('domready',function({
    //load the data
    $.get({
       url:'/charts/3D1A2E', 
       success: function(data){
           //now use the chart data here
           ChartModule.init(data);
       }
    });
})
roo2
quelle
-3

Dies ist keine schlechte Praxis, NUR wenn sie für die Initialisierung von Javascript-Code verwendet wird (in meinen WordPress-Themes initialisiere ich meine Javascript-Objekte mit PHP-Funktionen wie site_url ()), da dies die einzige Möglichkeit ist (möglicherweise können wir eine Ajax-Anfrage verwenden, um diese zu erhalten) ein Json, und so ... aber es ist ein Schmerz im Arsch).

Gute Übung:

neues JavascriptObject ("");

Schlechte Praxis:

/ * etwas Code * / document.get_element_by_id (); / * etwas Code * /
junius rendel
quelle