├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── examples ├── index.html ├── sse-swoole.php └── sse.php ├── src ├── Event.php ├── SSE.php ├── SSESwoole.php └── StopSSEException.php └── sse.png /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | .idea/ 3 | composer.lock 4 | examples/*.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dave 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHP SSE: Server-sent Events 2 | ====== 3 | 4 | A simple and efficient library implemented HTML5's server-sent events by PHP, is used to real-time push events from server to client, and easier than 5 | Websocket, instead of AJAX request. 6 | 7 | ## Requirements 8 | 9 | * PHP 5.4 or later 10 | 11 | ## Installation via Composer([packagist](https://packagist.org/packages/hhxsv5/php-sse)) 12 | 13 | ```BASH 14 | composer require "hhxsv5/php-sse:~2.0" -vvv 15 | ``` 16 | 17 | ## Usage 18 | 19 | ### Run demo 20 | 21 | - Run PHP webserver 22 | 23 | ```Bash 24 | cd examples 25 | php -S 127.0.0.1:9001 -t . 26 | ``` 27 | 28 | - Open url `http://127.0.0.1:9001/index.html` 29 | 30 |  31 | 32 | ### Javascript demo 33 | 34 | > Client: receiving events from the server. 35 | 36 | ```Javascript 37 | // withCredentials=true: pass the cross-domain cookies to server-side 38 | const source = new EventSource('http://127.0.0.1:9001/sse.php', {withCredentials: true}); 39 | source.addEventListener('news', function (event) { 40 | console.log(event.data); 41 | // source.close(); // disconnect stream 42 | }, false); 43 | ``` 44 | 45 | ### PHP demo 46 | 47 | > Server: Sending events by pure php. 48 | 49 | ```PHP 50 | use Hhxsv5\SSE\Event; 51 | use Hhxsv5\SSE\SSE; 52 | use Hhxsv5\SSE\StopSSEException; 53 | 54 | // PHP-FPM SSE Example: push messages to client 55 | 56 | header('Content-Type: text/event-stream'); 57 | header('Cache-Control: no-cache'); 58 | header('Connection: keep-alive'); 59 | header('X-Accel-Buffering: no'); // Nginx: unbuffered responses suitable for Comet and HTTP streaming applications 60 | 61 | $callback = function () { 62 | $id = mt_rand(1, 1000); 63 | $news = [['id' => $id, 'title' => 'title ' . $id, 'content' => 'content ' . $id]]; // Get news from database or service. 64 | if (empty($news)) { 65 | return false; // Return false if no new messages 66 | } 67 | $shouldStop = false; // Stop if something happens or to clear connection, browser will retry 68 | if ($shouldStop) { 69 | throw new StopSSEException(); 70 | } 71 | return json_encode(compact('news')); 72 | // return ['event' => 'ping', 'data' => 'ping data']; // Custom event temporarily: send ping event 73 | // return ['id' => uniqid(), 'data' => json_encode(compact('news'))]; // Custom event Id 74 | }; 75 | (new SSE(new Event($callback, 'news')))->start(); 76 | ``` 77 | 78 | ### Symfony and Laravel demo 79 | 80 | > Server: Sending events by Laravel or Symfony. 81 | 82 | ```PHP 83 | use Hhxsv5\SSE\SSE; 84 | use Hhxsv5\SSE\Event; 85 | use Hhxsv5\SSE\StopSSEException; 86 | 87 | // Action method in controller 88 | public function getNewsStream() 89 | { 90 | $response = new \Symfony\Component\HttpFoundation\StreamedResponse(); 91 | $response->headers->set('Content-Type', 'text/event-stream'); 92 | $response->headers->set('Cache-Control', 'no-cache'); 93 | $response->headers->set('Connection', 'keep-alive'); 94 | $response->headers->set('X-Accel-Buffering', 'no'); // Nginx: unbuffered responses suitable for Comet and HTTP streaming applications 95 | $response->setCallback(function () { 96 | $callback = function () { 97 | $id = mt_rand(1, 1000); 98 | $news = [['id' => $id, 'title' => 'title ' . $id, 'content' => 'content ' . $id]]; // Get news from database or service. 99 | if (empty($news)) { 100 | return false; // Return false if no new messages 101 | } 102 | $shouldStop = false; // Stop if something happens or to clear connection, browser will retry 103 | if ($shouldStop) { 104 | throw new StopSSEException(); 105 | } 106 | return json_encode(compact('news')); 107 | // return ['event' => 'ping', 'data' => 'ping data']; // Custom event temporarily: send ping event 108 | // return ['id' => uniqid(), 'data' => json_encode(compact('news'))]; // Custom event Id 109 | }; 110 | (new SSE(new Event($callback, 'news')))->start(); 111 | }); 112 | return $response; 113 | } 114 | ``` 115 | 116 | ### Swoole demo 117 | 118 | > Server: Sending events by Swoole Coroutine Http Server. 119 | > Install [Swoole](https://github.com/swoole/swoole-src) 4.5.x: `pecl install swoole`. 120 | 121 | ```php 122 | use Hhxsv5\SSE\Event; 123 | use Hhxsv5\SSE\SSESwoole; 124 | use Swoole\Http\Request; 125 | use Swoole\Http\Response; 126 | use Swoole\Http\Server; 127 | use Hhxsv5\SSE\StopSSEException; 128 | 129 | // Swoole SSE Example: push messages to client 130 | 131 | $server = new Server('0.0.0.0', 5200); 132 | $server->set([ 133 | 'enable_coroutine' => true, 134 | 'max_coroutine' => 10000, // worker_num*10000 135 | 'reactor_num' => swoole_cpu_num() * 2, 136 | 'worker_num' => swoole_cpu_num() * 2, 137 | 'max_request' => 100000, 138 | 'buffer_output_size' => 4 * 1024 * 1024, // 4MB 139 | 'log_level' => SWOOLE_LOG_WARNING, 140 | 'log_file' => __DIR__ . '/swoole.log', 141 | ]); 142 | 143 | $server->on('Request', function (Request $request, Response $response) use ($server) { 144 | $response->header('Access-Control-Allow-Origin', '*'); 145 | $response->header('Content-Type', 'text/event-stream'); 146 | $response->header('Cache-Control', 'no-cache'); 147 | $response->header('Connection', 'keep-alive'); 148 | $response->header('X-Accel-Buffering', 'no'); 149 | 150 | $event = new Event(function () { 151 | $id = mt_rand(1, 1000); 152 | $news = [['id' => $id, 'title' => 'title ' . $id, 'content' => 'content ' . $id]]; // Get news from database or service. 153 | if (empty($news)) { 154 | return false; // Return false if no new messages 155 | } 156 | $shouldStop = false; // Stop if something happens or to clear connection, browser will retry 157 | if ($shouldStop) { 158 | throw new StopSSEException(); 159 | } 160 | return json_encode(compact('news')); 161 | // return ['event' => 'ping', 'data' => 'ping data']; // Custom event temporarily: send ping event 162 | // return ['id' => uniqid(), 'data' => json_encode(compact('news'))]; // Custom event Id 163 | }, 'news'); 164 | (new SSESwoole($event, $request, $response))->start(); 165 | }); 166 | $server->start(); 167 | ``` 168 | 169 | ## License 170 | 171 | [MIT](https://github.com/hhxsv5/php-sse/blob/master/LICENSE) 172 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hhxsv5/php-sse", 3 | "type": "library", 4 | "license": "MIT", 5 | "description": "A simple and efficient library implemented HTML5's server-sent events by PHP, is used to real-time push events from server to client, and easier than Websocket, instead of AJAX request.", 6 | "keywords": [ 7 | "sse", 8 | "server-sent events", 9 | "eventsource", 10 | "events", 11 | "sever-events", 12 | "event-stream" 13 | ], 14 | "homepage": "https://github.com/hhxsv5/php-sse", 15 | "authors": [ 16 | { 17 | "name": "Xie Biao", 18 | "email": "hhxsv5@sina.com" 19 | } 20 | ], 21 | "require": { 22 | "php": ">=5.4" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "~6.0", 26 | "swoole/ide-helper": "@dev" 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Hhxsv5\\SSE\\": "src" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |