Ответ 1
Чтобы оценить код JavaScript с помощью PHP, ознакомьтесь с расширением движка V8 JavaScript, которое вы можете компилировать в ваш двоичный файл PHP:
Я генерирую вашу типичную HTML-страницу Web 2.0 с PHP: она содержит много тегов <script>
и javascript-код, которые существенно изменят DOM после события загрузки.
Есть ли способ получить окончательный код HTML непосредственно с PHP, не открывая страницу с помощью какого-либо браузера?
Например, скажем, HTML для страницы (это просто пример):
<html>
<head>
<script>...the jquery library code...</script>
<script>$(document).ready(function() { $("body").append("<p>Hi!</p>");</script>
</head>
<body>
</body>
</html>
Этот HTML сохраняется в переменной $html
PHP. Теперь я хочу передать эту переменную некоторой функции, которая вернет $result = <html>....<body><p>Hi!</p></body></html>
.
Возможно ли это?
EDIT: поскольку многие из вас были озадачены моей просьбой, я объясню причину. К сожалению, все пользовательские образы были сделаны в javascript, и это делает сайт неприступным для поисковых систем. Поэтому я хотел отправить им HTML-код события post-ready.
Чтобы оценить код JavaScript с помощью PHP, ознакомьтесь с расширением движка V8 JavaScript, которое вы можете компилировать в ваш двоичный файл PHP:
Лучшее решение, которое я смог найти, - использовать HtmlUnit http://htmlunit.sourceforge.net/ на сервере для выполнения вашего html с помощью javascript и возврата final html, который пользователь увидит в браузере.
Библиотека имеет хорошую поддержку JavaScript и безгласна, поэтому вы должны иметь возможность запускать ее на сервере.
Вам нужно будет написать небольшую оболочку Java, которая может принимать входные данные через командную строку и передавать ее на HtmlUnit для обработки, а затем возвращать результат. Затем вы можете вызвать эту оболочку из PHP.
У вас есть 2 проблемы:
Для запуска javascript вам понадобится механизм javascript. В настоящее время 3 доступны для вашего использования:
После того, как у вас есть механизм javascript, вам нужно будет управлять DOM (Document Object Model). Это позволяет анализировать HTML на такие объекты, как узлы DOM, текстовые узлы, элементы и т.д. Кроме того, вам нужно будет синхронизировать DOM с механизмом JavaScript и установить DOM-библиотеку в вашем javascript-движке. Хотя могут быть разные способы сделать это, я предпочитаю просто включать/оценивать автономный JavaScript DOM в движок и просто передавать HTML на это.
Теперь, когда у вас есть как JavaScript Engine, так и DOM-библиотека, вы можете теперь оценить большинство скриптов без проблем.
Лучший ответ
NodeJS, который поставляется как автономный исполняемый файл, имеет механизм javascript, а также манипулирование DOM в 1. Кроме того, вы можете использовать его как веб-сервер. Возможно, это лучшее решение вашей проблемы, однако, если PHP является обязательным, придерживайтесь того, что упоминалось выше.
Если я правильно понимаю, вы хотите выполнить JavaScript-функцию в PHP... JavaScript выполняется в браузере (на стороне клиента), PHP является серверным, поэтому, если вы не пишете JavaScript-парсер в PHP, это не сработает.
Почему JS-парсер на сервере имеет смысл вообще (я не могу придумать причину, почему это должно) или возможно в первую очередь, это еще один вопрос... JS будет работать над DOM, не существует на сервере, а также вызываются функции, которые бесполезны (подумайте о том, что "window.close()" будет/должно делать на сервере!?).
Итак, чтобы коротко ответить: №:)
Было бы возможно, если бы у вас был встроенный в PHP интерпретатор javascript (или, по крайней мере, что-то на сервере, которое вы могли бы вызвать для интерпретации HTML с встроенным javascript). Произошли некоторые попытки (например, http://j4p5.sourceforge.net/index.php), но я бы избежал этих и попытался переосмыслить то, что вы делаете. В зависимости от ваших конкретных потребностей шаблон (т.е. Что-то вроде Smarty) может решить часть вашей проблемы (он, однако, НЕ интерпретирует javascript, конечно).
Этот вопрос очень похож на выполнение javascript в javascript или php в php. Ответ заключается в том, что вы можете его оценить. Если php мог бы оценивать javascript, а javascript мог бы eval php, у нас не было бы этого обсуждения.
Для того, чтобы JavaScript для eval PHP, он должен разобрать PHP-код в структуру, которая представляет script. JavaScript может легко сделать это с помощью обозначения объекта JavaScript (не формата JSON, а фактического представления) и функционального разбиения script.
Здесь наивный пример JavaScript-интерпретации PHP (более честный пример не был бы настолько надуманным, но проанализировал бы php в своем собственном JSON-подобном представлении или, возможно, bytecode, затем интерпретировал бы это json-подобное представление или байт-код в javascript-эмуляции виртуальной машины php, но тем не менее):
(() => {
'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);
})();
Проблема в том, что PHP не является javascript и страдает от того, что он eval намного слабее, чем javascript.
Это создает проблему, при которой php может легко запросить tokenize javascript для PHP: JavaScript может легко создать "JSONified" версию чего угодно (до тех пор, пока она не является родной), поэтому вы могли бы PHP отправить запрос на сервер nodejs с script, который вы хотите оценить.
например: (код PHP)
include "some_file_defining_jsEval.php";
$wantedObject = function($a) {
return $a;
};
$resultingObject = jsEval(
'(function(a) {' .
' return a;' .
'})'
);
echo $resultingObject("Hello, World!");
JavaScript может легко преобразовать его в "объект функции", выполнив следующие действия:
var functionObject = eval(
'(function(a) {' +
' return a;' +
'})'
);
console.log('your code is: ' + '(' + functionObject.toString() + ')');
как вы можете видеть, js может легко проанализировать его в объекте и вернуться в строку с незначительной неприятностью, что '(' и ')' необходимо добавить, чтобы сделать ее eval(), не вызывая ошибки "Uncaught SyntaxError: Неожиданный токен (".
Независимо от того, что можно сделать в PHP:
<?php
$functionObject = eval(
'return function($a) {' .
' return $a;' .
'};'
);
echo $functionObject("hi");
?>
Зная это, вам нужно, чтобы JavaScript преобразовал объект функции JavaScript в объект функции PHP или перешел к простому маршруту только для перевода.
Проблема заключается в том, что JavaScript (ES6) гораздо более выразителен, чем PHP (5.6, 7 может быть лучше, но он не работает без окна пакета обновления 1, поэтому я не могу запустить его на этом компьютере), Это, в свою очередь, означает множество функций JavaScript, у которых PHP отсутствует, например:
(function() {
console.log("Hello World");
})();
Не будет работать на PHP 5.6, потому что он не поддерживает функции самостоятельного выполнения. Это означает, что вам нужно сделать больше работы, чтобы перевести его на:
call_user_func(function() {
echo "hello, world!" . "\n";
});
Есть также проблемы в том, что PHP не использует прототипы так, как делает javascript, поэтому очень сложно сделать перевод этого.
В любом случае, в конечном счете php и javascript очень похожи, поэтому вы можете использовать один в другом с исключениями.
например: (PHP)
/* не может описать как функцию, насколько я знаю, поскольку не прототип */ class console { статический журнал функций ($ text) { echo $text. "\ П"; } };
call_user_func (function() { $ myScopeVariable = "Эй, это не JavaScript!"; консоли:: журнал ($ myScopeVariable); });
например. JavaScript:
/* javascript requires brackets because semicolons are not mandatory */
var almost_echo = (console.log.bind(console));
Заключение
Вы можете переводить между PHP и JavaScript, но гораздо проще перевести PHP на JavaScript, чем JavaScript на PHP, потому что JavaScript более выразителен изначально, тогда как PHP должен создавать классы для представления многих конструкций JavaScript (достаточно смешно, php может препроцесс php, чтобы исправить все эти проблемы).
К счастью, PHP теперь может иметь смысл JSON изначально, поэтому после того, как javascript оценивает себя, javascript может прочитать полученную структуру (большинство вещей в JavaScript - это объекты или функции), включая исходный код, и помещать эти объекты в JSON-кодированные форма. После этого вы можете заставить PHP разобрать JSON для восстановления кода через нейтральную форму).
например.
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; }
По существу, общение через "Common LISP", так сказать. Конечно, это будет очень дорого, а не родной, но это прекрасно, чтобы продемонстрировать пример. В идеале у нас бы был встроенный модуль, инкапсулирующий скрипты любого типа, которые могли бы легко перевести ruby на php на perl на python на javascript, а затем скомпилировать результат для c). javascript помогает приблизиться к этому, будучи в состоянии предсказать себя как хорошо, как распечатать свой собственный код. Если бы все языки могли выполнять обе эти вещи, было бы намного проще выполнить, но, к сожалению, javascript только "почти там" (нет функции un-eval, вы можете легко придумать ее, но ее еще нет)
Как для обновления DOM. PHP может делать это так же легко, как JavaScript. Проблема в том, что как javascript, так и php не имеют представления о том, что такое DOM, это просто то, что в браузере dom удобно подключается как "оконный" объект. Вы просто действуете так, как будто окно есть, и по мере того как php получает оценку javascript, он снова получит доступ к DOM. Однако, чтобы использовать dom, код должен быть "обратным вызовом", поскольку он не получит dom до его оценки, но это не так, вы просто ничего не делаете, пока оценка не будет завершена, а затем выполните все действия сразу после того, как dom доступен.
Код выглядит примерно так:
(() => {
var php_code = `
function ($window) {
$window::document::getElementById('myDIV')->innerHTML = "Hello, World!";
};
`;
window.addEventListener('load', () => {
(eval(php_code(window)))();
});
})();
Хотя правильный способ - это оценить функцию для обещания (promises являются универсальными... как только вы реализуете их на всех языках...). После этого он просто становится вопросом жонглирования promises/намерений, которые, по сути, независимы от языка (Чтобы быть конкретными, намерение не зависит от языка, как только намерение будет переведено, намерение потребует зависимости, которые могут или не могут быть предоставлены на самом деле выполните последовательность от начала до конца).
Надеемся, что когда-нибудь мы увидим будущее, где JavaScript может оценить PHP, и PHP может легко оценить JavaScript, по крайней мере, заполнить круг путаницы, позволяющий нам писать javascript на стороне клиента и стороне сервера (мы на полпути! )
некоторые конечные мысли
php, perl, lisp и другие синонимы лямбда-исчисления нуждаются в собственном встроенном варианте JSON. Это в основном eval и uneval, но проще в том, что он не заботится о более захватывающих структурах данных, таких как функции (которые JavaScript может неспециализировать, используя toString несколько, и Perl может использовать Data:: Dumper с Data:: Dumper:: Deparse, установленным для 1).
каждый язык синонимов лямбда-исчисления (php, perl, lisp,..., где утверждение (function(a){return function(b){return a + b;}})(2)(3)
имеет смысл (наивно даже сборка может сделать это с помощью копания стека, поэтому его несколько лямбда-исчисление язык синонимов, а также может иметь собственный вариант JSON) должны иметь возможность кодировать строку действительного кода в общее абстрактное представление, которое может быть закодировано и декодировано с любого языка синонимов лямбда-исчисления.
Я сомневаюсь, что есть несколько хороших серверных сред общего назначения для браузера JavaScript в целом и в PHP. Для сложных клиентских скриптов нет такой вещи, как "конечное состояние DOM". Представьте, что какой-то метод обновления DOM запланирован с помощью setTimeout
. Вы хотите подождать? И если он перенастроит другое обновление таким же образом (например, чтобы показать текущее время где-то на странице), как долго вы будете ждать? А что, если страница загружает некоторые данные AJAX? Вы хотите выполнять фактические запросы сервера, эмулировать файлы cookie и т.д.? Я думаю, что это слишком сложно, чтобы быть реализованы в хорошем смысле. Ну, может быть, у Google есть что-то подобное в своем искателе, но он специализируется на своих конкретных потребностях.
Я столкнулся с такой же проблемой при создании веб-искателя. Вы можете получить окончательную DOM с помощью браузера без браузера, такого как PhantomJS. Вы в основном говорите, что PhantomJS загружает данные для вас и выгружает нужные данные.
Если вы используете PHP, для выполнения задания есть оболочка php-phantomjs.
Появились новые серверы, которые запускают Javascript на стороне сервера и могут манипулировать DOM, но это не имеет ничего общего с PHP.
<?php
function visible()
{
echo '<script type="text/javascript">
var o = document.getElementById("overlay");
o.style.visibility = "visible";
</script>';
}
?>
Это хороший способ, который я часто использовал для запуска javascript в php
<?php
function visible()
{
return ('<script type="text/javascript">var o = document.getElementById("cf");
document.write(o.innerHTML);
</script>');
}
echo visible();
?>