Еще одна безумная идея. Я хочу вывести свой бэкэнд-вывод в консоль браузера. Есть несколько дамперов PHP. Например, Божья коровка Рауля Фрейля . Также есть библиотеки, которые делают именно то, что я хочу, например Chrome Logger . Но я хотел использовать Websockets и выводить значения в режиме реального времени, не дожидаясь окончания бэкэнд-скрипта. Зачем? Ответ прост: потому что я хотел сделать это ?
Я написал несколько постов о Websockets, Silex, PHP. В этом случае я буду использовать аналогичный подход, чем предыдущие посты. Сначала я создал простой сервер Webscocket с socket.io. Этот сервер также запускает сервер Express для обработки внутренних сообщений от Silex Backend
var CONF = {
IO: {HOST: '0.0.0.0', PORT: 8888},
EXPRESS: {HOST: '0.0.0.0', PORT: 26300}
},
express = require('express'),
expressApp = express(),
server = require('http').Server(expressApp),
io = require('socket.io')(server, {origins: 'localhost:*'})
;
expressApp.get('/:type/:session/:message', function (req, res) {
console.log(req.params);
var session = req.params.session,
type = req.params.type,
message = req.params.message;
io.sockets.emit('dumper.' + session, {title: type, data: JSON.parse(message)});
res.json('OK');
});
io.sockets.on('connection', function (socket) {
console.log("Socket connected!");
});
expressApp.listen(CONF.EXPRESS.PORT, CONF.EXPRESS.HOST, function () {
console.log('Express started');
});
server.listen(CONF.IO.PORT, CONF.IO.HOST, function () {
console.log('IO started');
});
Теперь мы создаем простого сервис-провайдера для подключения нашего Silex Backend к нашему серверу Express (и отправляем сообщения самосвала с помощью соединения через websocket)
<?php
namespace Dumper\Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Dumper\Dumper;
use Silex\Provider\SessionServiceProvider;
use GuzzleHttp\Client;
class DumperServiceProvider implements ServiceProviderInterface
{
private $wsConnector;
private $client;
public function __construct(Client $client, $wsConnector)
{
$this->client = $client;
$this->wsConnector = $wsConnector;
}
public function register(Application $app)
{
$app->register(new SessionServiceProvider());
$app['dumper'] = function () use ($app) {
return new Dumper($this->client, $this->wsConnector, $app['session']->get('uid'));
};
$app['dumper.init'] = $app->protect(function ($uid) use ($app) {
$app['session']->set('uid', $uid);
});
$app['dumper.uid'] = function () use ($app) {
return $app['session']->get('uid');
};
}
public function boot(Application $app)
{
}
}
Наконец, наше приложение Silex выглядит так:
include __DIR__ . '/../vendor/autoload.php';
use Silex\Application;
use Silex\Provider\TwigServiceProvider;
use Dumper\Silex\Provider\DumperServiceProvider;
use GuzzleHttp\Client;
$app = new Application([
'debug' => true
]);
$app->register(new DumperServiceProvider(new Client(), 'http://192.168.1.104:26300'));
$app->register(new TwigServiceProvider(), [
'twig.path' => __DIR__ . '/../views',
]);
$app->get("/", function (Application $app) {
$uid = uniqid();
$app['dumper.init']($uid);
return $app['twig']->render('index.twig', [
'uid' => $uid
]);
});
$app->get('/api/hello', function (Application $app) {
$app['dumper']->error("Hello world1");
$app['dumper']->info([1,2,3]);
return $app->json('OK');
});
$app->run();
На стороне клиента у нас есть один index.html. Я создал шаблон Twig для передачи uid объекту dumper (каналу websocket для прослушивания), но мы также можем извлечь этот uid из серверной части одним вызовом ajax.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Dumper example</title>
</head>
<body>
<a href="#" onclick="api('hello')">hello</a>
<!-- We use jQuery just for the demo. Library doesn't need jQuery -->
<script src="assets/jquery/dist/jquery.min.js"></script>
<!-- We load the library -->
<script src="js/dumper.js"></script>
<script>
dumper.startSocketIo('{{ uid }}', '//localhost:8888');
function api(name) {
// we perform a remote api ajax call that triggers websockets
$.getJSON('/api/' + name, function (data) {
// Doing nothing. We only call the api to test php dumper
});
}
</script>
</body>
</html>
Я использую jQuery для обработки ajax-запроса и подключения к объекту дампа websocket (он не зависит от jQuery, зависит только от socket.io)
var dumper = (function () {
var socket, sessionUid, socketUri, init;
init = function () {
if (typeof(io) === 'undefined') {
setTimeout(init, 100);
} else {
socket = io(socketUri);
socket.on('dumper.' + sessionUid, function (data) {
console.group('Dumper:', data.title);
switch (data.title) {
case 'emergency':
case 'alert':
case 'critical':
case 'error':
console.error(data.data);
break;
case 'warning':
console.warn(data.data);
break;
case 'notice':
case 'info':
//case 'debug':
console.info(data.data);
break;
default:
console.log(data.data);
}
console.groupEnd();
});
}
};
return {
startSocketIo: function (uid, uri) {
var script = document.createElement('script');
var node = document.getElementsByTagName('script')[0];
sessionUid = uid;
socketUri = uri;
script.src = socketUri + '/socket.io/socket.io.js';
node.parentNode.insertBefore(script, node);
init();
}
};
})();