我使用PHP exec()
安装Composer依赖项:
exec('php composer.phar install -d ' . dirname(__DIR__), $out);
这是通过ajax post请求触发的。一切工作正常,从exec()
返回打印到屏幕上。
exit(json_encode($out));
然而,我所追求的是一种定期将数据发送回ajax回调的方法,这样我就可以呈现每个信息位,而不是一次呈现整个块。
不确定这是否可能。
我应该提到的是,运行这个脚本的服务器不会有NodeJS这样的东西,而且很可能是共享主机。
抛开按需执行的安全问题不谈,如果您能够将输出的状态写入/记录到文件中,您可以编写一个简单的AJAX轮询器(因为您不喜欢使用WebSockets)。
在您的执行中,尝试:
add-task.php
$jobId = uniqid();
$outfile = $jobId . "-results.txt";
exec('php composer.phar install -d ' . dirname(__DIR__) . " > $outfile &", $out);
$result = array("jobId" => $jobId);
echo json_encode($result);
Ok,现在将$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>