#php #ajax #bash #composer-php #command-line-interface
#php #ajax #bash #композитор-php #интерфейс командной строки
Вопрос:
Я использую PHP exec()
для установки зависимостей Composer:
exec('php composer.phar install -d ' . dirname(__DIR__), $out);
Это запускается с помощью запроса ajax post. Все работает нормально, и возврат из exec()
выводится на экран.
exit(json_encode($out));
Однако мне нужен способ периодической отправки данных обратно в обратный вызов ajax, чтобы я мог отображать каждый бит информации, а не весь блок сразу.
Хотя не уверен, возможно ли это.
Я должен упомянуть, что серверы, на которых это будет выполняться, не будут иметь ничего похожего на NodeJS и, скорее всего, будут общедоступным хостингом.
Комментарии:
1. Я думаю,
WebSocket
s может помочь.2. Я бы предпочел не использовать websockets, поскольку мне нужно поддерживать некоторые старые браузеры (IE)
3. Как? Основная проблема заключается в том, что Carl создает поток данных, но затем передает его в виде дейтаграммы.
4. После открытия соединения он мог передавать фрагменты данных на другую сторону. Чтобы реализовать это только с помощью Ajax, вам нужно будет создать конечный автомат, но это может легко усложниться.
5. Существуют решения для websockets в IE6 с использованием flash github.com/arahaya/FlashSocket
Ответ №1:
Если оставить в стороне проблемы безопасности выполнения по требованию, если вы можете записать / протоколировать статус выходных данных в файл, вы можете написать простой AJAX-опросник (поскольку вы предпочитаете не использовать WebSockets).
В вашем exec попробуйте:
add-task.php
$jobId = uniqid();
$outfile = $jobId . "-results.txt";
exec('php composer.phar install -d ' . dirname(__DIR__) . " > $outfile amp;", $out);
$result = array("jobId" => $jobId);
echo json_encode($result);
Хорошо, теперь отправьте это $jobId
клиенту, чтобы он мог опрашивать обновления. Я использую вариант концептуального проекта на github:https://github.com/panique/php-long-polling
server.php
$jobid = isset($_GET['jobid']) ? $_GET['jobid'] : null;
$outputfile = $jobid . "-results.txt";
$lastTimestamp = isset($_GET['timestamp']) ? (int)$_GET['timestamp'] : null;
// get timestamp of when file has been changed the last time
clearstatcache();
$lastModified = filemtime($outputfile);
// if no timestamp delivered via ajax
// or data.txt has been changed SINCE last ajax timestamp
if ($lastTimestamp == null || $lastModified > $lastTimestamp) {
// get content of data.txt
$data = file_get_contents($outputfile);
// put data.txt's content and timestamp of
// last data.txt change into array
$result = array(
'data' => $data,
'timestamp' => $lastTimestamp
);
// encode to JSON, render the result (for AJAX)
$json = json_encode($result);
} else {
// No updates in the file, just kick back the current time
// and the client will check back later
$result = array(
'timestamp' => time()
);
$json = json_encode($result);
}
header("Content-Type: application/json");
echo $json;
Затем в браузере у вас просто есть крошечный клиент, который запрашивает ‘jobid’ для проверки статуса.
client.js
$(function () {
var jobid = '12345';
function checkForUpdates(timestamp) {
$.ajax({
type: 'GET',
url: 'http://localhost/server.php',
data: {
'timestamp': timestamp,
'jobid': jobid
},
success: function (data) {
var obj = jQuery.parseJSON(data);
if (obj.data) {
// Update status content
$('#response').text(obj.data);
}
// Check again in a second
setTimeout(function () {
checkForUpdates(obj.timestamp);
}, 1000);
}
});
}
checkForUpdates();
});
index.html
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="client.js"></script>
</head>
<body>
<h1>Status:</h1>
<div><pre id="response"></pre></div>
</body>
</html>