it-swarm.com.de

Führen Sie Javascript in PHP

Ich erstelle eine typische Web 2.0-HTML-Seite mit PHP: Sie enthält viele <script>-Tags und Javascript-Code, die das DOM nach dem Ladeereignis erheblich verändern.

Gibt es eine Möglichkeit, den endgültigen HTML-Code direkt von PHP abzurufen, ohne die Seite mit einem Browser zu öffnen?

Angenommen, der HTML-Code für die Seite lautet (nur ein Beispiel):

<html>
<head>
<script>...the jquery library code...</script>
<script>$(document).ready(function() { $("body").append("<p>Hi!</p>");</script>
</head>
<body>
</body>
</html>

Dieser HTML-Code wird in der Variablen $html PHP gespeichert. Nun möchte ich diese Variable an eine Funktion übergeben, die $ result = <html>....<body><p>Hi!</p></body></html> zurückgibt.

Ist das möglich?

EDIT: da viele von euch von meiner Bitte verwirrt waren, erkläre ich den Grund. Leider wurde alles, was den Nutzern angezeigt wird, in Javascript erstellt und dies macht die Website für Suchmaschinen nicht durchsuchbar. Deshalb wollte ich ihnen stattdessen den Post-Ready-Event-HTML-Code senden.

14
Andreas Bonini

Um JavaScript-Code mit PHP auszuwerten, werfen Sie einen Blick auf die V8-JavaScript-Engine-Erweiterung , die Sie in Ihre PHP-Binärdatei kompilieren können:

V8 ist Googles Open-Source-JavaScript-Implementierung .

22
SteAp

Die beste Lösung, die ich finden konnte, ist, HtmlUnit http://htmlunit.sourceforge.net/ auf dem Server zu verwenden, um Ihr HTML mit dem Javascript auszuführen und das endgültige HTML zurückzugewinnen, das der Benutzer im Browser sehen würde.

Die Bibliothek bietet eine gute Unterstützung für JavaScript und ist ohne Kopf, sodass Sie sie auf dem Server ausführen können sollten.

Sie müssten einen kleinen Java-Wrapper schreiben, der Eingaben über die Befehlszeile akzeptieren und zur Verarbeitung an HtmlUnit übergeben und das Ergebnis dann an Sie zurückgeben kann. Sie können diesen Wrapper dann von PHP aus aufrufen.

9
Sijin

Sie haben 2 Probleme:

  1. Führen Sie JavaScript aus.
  2. Aktualisieren Sie DOM (das HTML nach dem Ausführen von Javascript).

Um Javascript ausführen zu können, benötigen Sie eine Javascript-Engine. Derzeit stehen Ihnen 3 zur Verfügung:

  1. V8 : Von Google für Chrome. PHP Erweiterung.
  2. Rhino : Von Mozilla für Firefox. Nur in Java verfügbar.
  3. JavaScriptCore : Von Apple für Safari. Nur in C erhältlich.

Sobald Sie eine JavaScript-Engine haben, müssen Sie DOM (Document Object Model) verwalten. Auf diese Weise können Sie HTML in Objekte wie DOM-Knoten, Textknoten, Elemente usw. analysieren. Außerdem müssen Sie Ihr DOM mit der JavaScript-Engine synchronisieren und die DOM-Bibliothek in Ihrer JavaScript-Engine installieren. Obwohl es verschiedene Möglichkeiten gibt, dies zu tun, ziehe ich es vor, einfach ein eigenständiges JavaScript-DOM in die Engine aufzunehmen/auszuwerten und einfach HTML an dieses zu übergeben.

  1. Env-JS JavaScript-DOM-Bibliothek. Kompatibel mit Prototyp/jQuery.
  2. jsdom JavaScript-DOM-Bibliothek für NodeJS.

Nachdem Sie sowohl eine JavaScript-Engine als auch eine DOM-Bibliothek haben, können Sie jetzt die meisten Skripts ohne Probleme auswerten.

Beste Antwort

NodeJS, das als eigenständige ausführbare Datei geliefert wird, verfügt über eine JavaScript-Engine sowie DOM-Manipulation in 1. Darüber hinaus können Sie es auch als Webserver verwenden. Vielleicht ist dies eine bessere Lösung für Ihr Problem, aber wenn PHP ein Muss ist, halten Sie sich an die oben genannten Punkte.

5
mAsT3RpEE

Diese Frage ist sehr ähnlich, wie man Javascript in Javascript oder PHP in PHP ausführt. Die Antwort ist, dass Sie es auswerten können. Wenn PHP Javascript und Javascript PHP auswerten könnte, hätten wir diese Diskussion nicht.

Damit JavaScript PHP auswerten kann, muss es den Code PHP in eine Struktur zerlegen, die das Skript darstellt. JavaScript kann dies problemlos mit der JavaScript-Objektnotation (nicht im JSON-Format, sondern in der tatsächlichen Darstellung) durchführen und das Skript funktional auflösen.

Hier ist ein naives Beispiel für die Interpretation von PHP durch JavaScript (ein ehrlicheres Beispiel wäre nicht so erfunden, aber analysieren Sie das PHP in eine eigene JSON-ähnliche Darstellung oder einen möglichen Bytecode, und interpretieren Sie dann diese json-ähnliche Darstellung oder den Bytecode in einer JavaScript-Emulation des PHP virtuelle Maschine, aber trotzdem):

(() => {
    'use strict';

    var phpSnippet = 'echo "Hi";';    

    var partialPHPEval = (phpCode) => {
        var regex = /echo[\s]["]([^"]*)["][;]/mg;
        var match = null;
        phpCode = phpCode.trim();

        if ((match = phpCode.match(regex))) {
            var code = (match[0].replace(regex, "(console.log('$1'))"));
            console.log('converted to "' + code + '"');

            eval(code);
        }        
    };

    partialPHPEval(phpSnippet);  
})();

Das Problem ist, dass PHP kein Javascript ist und unter der Tatsache leidet, dass es viel schwächer ist als Javascript.

Dies führt zu einem Problem, bei dem PHP die Tokenisierung von Javascript in PHP auf einfache Weise anfordert: JavaScript kann auf einfache Weise eine "JSONified" -Version von allem erstellen (solange es nicht nativ ist), sodass Sie PHP Sende eine Anfrage an einen NodeJS-Server mit dem Skript, das du auswerten möchtest.

zum Beispiel: (PHP-Code)

include "some_file_defining_jsEval.php";

$wantedObject = function($a) {
    return $a;
};

$resultingObject = jsEval(
    '(function(a) {' .
    '    return a;' .
    '})'
);

echo $resultingObject("Hello, World!");

JavaScript kann es leicht zu einem "Funktionsobjekt" auswerten, indem es Folgendes ausführt:

var functionObject = eval(
    '(function(a) {' +
    '    return a;' +
    '})'
);

console.log('your code is: ' + '(' + functionObject.toString() + ')');

wie Sie sehen können, kann js es leicht in ein Objekt und zurück in einen String analysieren, mit einem kleinen Nachteil, dass '(' und ')' hinzugefügt werden müssen, um es eval () zu machen, ohne einen Fehler zu verursachen. "Uncaught SyntaxError : Unerwartetes Token (".

Unabhängig davon kann in PHP Folgendes ausgeführt werden:

<?php

$functionObject = eval(
    'return function($a) {' .
    '    return $a;' .
    '};'
);

echo $functionObject("hi");
?>

Wenn Sie dies wissen, muss JavaScript das JavaScript-Funktionsobjekt in ein PHP -Funktionsobjekt konvertieren, oder Sie müssen einfach nur übersetzen.

Das Problem liegt in der Tatsache, dass JavaScript (ES6) viel aussagekräftiger ist als PHP (5.6, 7 könnte besser sein, aber es funktioniert nicht ohne Service Pack 1 Windows 7, so dass ich es nicht auf diesem Computer ausführen kann). Dies bedeutet wiederum, dass JavaScript viele Funktionen hat, die PHP nicht hat, zum Beispiel:

(function() {
    console.log("Hello World");
})();

Funktioniert nicht mit PHP 5.6, da es keine selbstausführenden Funktionen unterstützt. Das bedeutet, dass Sie mehr Arbeit erledigen müssen, um es zu übersetzen:

call_user_func(function() {
    echo "hello, world!" . "\n";
});

Es gibt auch Probleme darin, dass PHP Prototypen nicht so verwendet wie Javascript, daher ist es sehr schwierig, diese zu übersetzen.

Wie auch immer, letztendlich sind PHP und Javascript SEHR ähnlich, so dass Sie im Wesentlichen eins in dem anderen mit Ausnahmen verwenden können.

z. B .: (PHP)

/ * kann meines Wissens nicht als Funktion beschreiben, da */class console {statisches Funktionsprotokoll ($ text) {echo $ text nicht prototypisch ist. "\ n"; }};

call_user_func (function () {$ myScopeVariable = "Hey, das ist kein JavaScript!"; console :: log ($ myScopeVariable);});

z.B. JavaScript:

/* javascript requires brackets because semicolons are not mandatory */
var almost_echo = (console.log.bind(console));

Fazit

Sie können zwischen PHP und JavaScript übersetzen, aber es ist viel einfacher, PHP in JavaScript zu übersetzen als JavaScript in PHP, da JavaScript von Haus aus aussagekräftiger ist, während PHP muss Klassen erstellen, um viele JavaScript-Konstrukte darzustellen (lustig genug, PHP kann PHP vorverarbeiten, um all diese Probleme zu beheben).

Glücklicherweise kann PHP JSON jetzt nativ verstehen. Nachdem sich Javascript selbst ausgewertet hat, kann Javascript die resultierende Struktur (die meisten Dinge in JavaScript sind Objekte oder Funktionen), einschließlich des Quellcodes, lesen und diese Objekte darin ablegen JSON-codierte Form. Danach können Sie PHP den JSON analysieren lassen, um den Code über eine neutrale Form wiederherzustellen.

z.B.

php: jsEval('function(a){return a;}');
js: [{"type":"function", "name": "foo", "args":["a"], body: "return a"}]
php: oh, i get it, you mean 
function foo($a) { return $a; } 

Im Wesentlichen über ein "Common LISP" sozusagen kommunizieren. Natürlich wird dies sehr teuer und nicht einheimisch sein, aber es ist in Ordnung, ein Beispiel zu zeigen. Idealerweise hätten wir ein natives Modul, das Skripte aller Art enthält, die Ruby leicht in PHP in Perl in Python in Javascript übersetzen und das Ergebnis dann zum Teufel in c kompilieren könnten. Javascript hilft, sich dem anzunähern, indem es sich AUCH selbst auswertet und seinen eigenen Code druckt. Wenn alle Sprachen beides könnten, wäre es viel einfacher zu erreichen, aber leider ist Javascript nur "fast da" (es gibt keine uneval-Funktion, Sie können es leicht erfinden, aber es ist noch nicht da).

Wie für die Aktualisierung von DOM. PHP kann es so einfach wie JavaScript. Das Problem ist, dass sowohl Javascript als auch PHP keine Ahnung haben, was DOM ist. Es ist nur so, dass der Dom im Browser bequem als "Fenster" -Objekt angehängt wird. Sie tun einfach so, als ob das Fenster vorhanden wäre, und wenn die PHP-Version auf Javascript ausgewertet wird, erhält sie wieder Zugriff auf das DOM. Um dom nutzen zu können, muss der Code "Callback-orientiert" sein, da er erst nach der Auswertung dom erhält, aber es ist nicht schlimm, Sie tun einfach nichts, bis die Auswertung abgeschlossen ist, und führen dann die aus ganze Aktion auf einmal, nachdem dom verfügbar ist.

Der Code würde ungefähr so ​​aussehen:

(() => {

    var php_code = `
function ($window) {
    $window::document::getElementById('myDIV')->innerHTML = "Hello, World!";
};
    `;

    window.addEventListener('load', () => {
        (eval(php_code(window)))();
    });
})();

Obwohl die richtige Methode darin besteht, die Funktion zu einem Versprechen auswerten zu lassen (Versprechen sind universell ... sobald Sie sie in allen Sprachen implementieren ...). Danach geht es nur noch darum, Versprechen/Absichten zu jonglieren, die im Wesentlichen sprachunabhängig sind. (Um genau zu sein, die Absicht ist sprachunabhängig. Sobald die Absicht übersetzt ist, erfordert die Absicht Abhängigkeiten, die bereitgestellt werden können oder nicht, um die tatsächlich auszuführen Sequenz von Anfang bis Ende).

Wir hoffen, dass wir eines Tages eine Zukunft sehen werden, in der JavaScript PHP und PHP JavaScript nahtlos auswerten können, um zumindest den Verwirrungskreis zu schließen, der es uns ermöglicht, clientseitig PHP und serverseitig zu schreiben Javascript (wir sind auf halbem Weg da!)

einige abschließende Gedanken

  1. php, Perl, LISP und andere Lambda-Kalkül-Synonyme benötigen eine eigene eingebaute Variante von JSON. Es ist im Grunde genommen eval und uneval, aber einfacher, da es die aufregenderen Datenstrukturen wie Funktionen nicht berücksichtigt (die JavaScript mit toString etwas unevalieren kann und Perl mit Data :: Dumper mit Data :: Dumper :: Deparse auf 1).

  2. jede Synonymsprache für Lambda-Kalkül (php, Perl, LISP, ..., wobei die Anweisung (function(a){return function(b){return a + b;}})(2)(3) sinnvoll ist (naiv kann dies auch Assembly mit Stack Digging tun, es ist also eine Art Synonymsprache für Lambda-Kalkül, und es kann auch eine eigene Variante haben von JSON) sollte in der Lage sein, eine Zeichenfolge gültigen Codes in eine gemeinsame abstrakte Darstellung zu codieren, die in jede andere Lambda-Kalkül-Synonymsprache codiert und daraus decodiert werden kann.

    1. die Prinzipien der funktionalen Programmierung schreiben vor, dass jede Aktion in eine Aufforderung zur Ausführung der Aktion zerlegt werden kann. Dabei handelt es sich um eine Transformatierung einer "Festschreibungsliste", die Festschreibungen stapelt, ohne sie auszuführen, und die Festschreibungen dann tatsächlichen Transformationen der globalen Umgebung zuordnet (entweder rein, durch Erstellen einer neuen Umgebung und Ausführen der Schwanzrekursion/Einreihen in die Warteschlange, damit die zukünftigen Aktionen mit der neuen Umgebung funktionieren, oder Unreinheit durch Mutation des globalen Zustands und Weitergehen, wobei beide gleichwertig mit geeigneten Abstraktionsmechanismen sind. Dies bedeutet, dass Sie ein PHP-Skript in einer Ajax-Anfrage senden, den Server symbolisch auf Dummy-Commit-Objekten ausführen lassen und dann eine Liste von Aktionen an den Client zurückgeben können, die erforderlich sind, damit es wie ausgeführtes PHP aussieht.
4
Dmitry

Es wäre möglich, wenn Sie einen Javascript-Interpreter in PHP eingebaut hätten (oder zumindest etwas auf dem Server, das Sie aufrufen könnten, um den HTML-Code mit eingebettetem Javascript zu interpretieren). Es gab einige Versuche (z. B. http://j4p5.sourceforge.net/index.php ), aber ich würde diese vermeiden und versuchen, Ihre Aktivitäten zu überdenken. Abhängig von Ihren spezifischen Anforderungen kann ein Template (zB Smarty ) Ihr Problem teilweise lösen (Javascript wird jedoch NICHT interpretiert).

3
wimvds

Wenn ich Sie richtig verstehe, möchten Sie eine JavaScript-Funktion in PHP ausführen ... JavaScript wird im Browser (clientseitig) ausgeführt, PHP ist serverseitig, Wenn Sie also keinen JavaScript-Parser in PHP schreiben, funktioniert das nicht.

Warum ein JS-Parser auf dem Server überhaupt Sinn macht (ich kann mir keinen Grund vorstellen, warum) oder überhaupt möglich ist, ist eine andere Frage ... JS wird auf einem DOM funktionieren, das nicht funktioniert auf dem Server existieren sowie Funktionen aufgerufen werden, die nutzlos sind (überlegen Sie, was "window.close ()" auf dem Server tun würde/sollte !?).

Um die Antwort kurz zu machen: Nein :)

2
Select0r

Beim Erstellen eines Webcrawlers trat das gleiche Problem auf. Sie können das endgültige DOM mithilfe eines Headless-Browsers wie PhantomJS abrufen. Sie weisen PhantomJS grundsätzlich an, die Daten für Sie zu laden und die gewünschten Daten zu sichern.

Wenn Sie PHP verwenden, gibt es einen Wrapper, php-phantomjs , um die Arbeit zu erledigen.

1
Hyder B.

Ich bezweifle, dass es einige gute allgemeine serverseitige Laufzeiten für Browser-JavaScript im Allgemeinen und in PHP im Besonderen gibt. Für komplizierte Client-Skripte gibt es keinen "finalen DOM-Status". Stellen Sie sich vor, dass eine DOM-Aktualisierungsmethode mit setTimeout geplant ist. Willst du darauf warten? Und wenn es ein anderes Update auf die gleiche Weise neu plant (zum Beispiel um die aktuelle Zeit irgendwo auf der Seite anzuzeigen), wie lange werden Sie warten? Und was ist, wenn auf einer Seite AJAX Daten heruntergeladen werden? Möchten Sie aktuelle Serveranfragen durchführen, Cookies emulieren usw.? Ich denke, das ist viel zu kompliziert, um es gut umzusetzen. Vielleicht hat Google so etwas in seinem Crawler, aber es ist auf seine besonderen Bedürfnisse spezialisiert.

0
SergGr