├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── examples ├── echo-server.php ├── fcgi.php ├── http-cookie.php ├── http-rest.php ├── http-route-adavanced.php ├── http-route.php ├── http.php ├── timeout.php ├── ws-chat │ ├── html │ │ └── index.html │ └── ws.php ├── ws-dynamic.php ├── ws-echo.php ├── ws-more.php └── ws-timeout.php ├── src ├── Attribute.php ├── Config.php ├── Console.php ├── EmitException.php ├── Event │ ├── EventEmitter.php │ ├── GlobalEventEmitter.php │ ├── Heap.php │ └── ResourceEventEmitter.php ├── FCGI │ ├── FCGI.php │ ├── FCGIServer.php │ ├── FCGIServerRequest.php │ ├── FCGIServerResponse.php │ └── FCGIUtil.php ├── GlobalConfig.php ├── HTTP │ ├── HTTP.php │ ├── HTTPRoute.php │ ├── HTTPServer.php │ ├── HTTPServerRequest.php │ ├── HTTPServerResponse.php │ └── HTTPUtil.php ├── Loop.php ├── NetConnection.php ├── Router │ ├── Matcher.php │ ├── PathMatcher.php │ └── Route.php ├── Server.php ├── ServerResponse.php ├── StreamSocket.php ├── Timeout.php └── WS │ ├── WS.php │ ├── WSApplication.php │ ├── WSFrame.php │ ├── WSNetConnection.php │ ├── WSServer.php │ ├── WSServerRequest.php │ ├── WSServerResponse.php │ └── WSUtil.php └── tests ├── EventEmitterTest.php ├── ResourceEventEmitterTest.php ├── RouteTest.php ├── ServerTest.php └── WSFrameTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ryohei Nagatsuka 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # EmitPHP 3 | 4 | EmitPHP is a PHP framework that works with non-blocking I/O. 5 | 6 | You can write your web applications and APIs in HTTP, FCGI and WebSocket. 7 | 8 | As of now, this is an experimental project and there still exists errors and bugs. 9 | 10 | ## Installation 11 | 12 | - It requires PHP 7(CLI) and composer to run 13 | - If you haven't installed composer, run below to install it. 14 | ```sh 15 | curl -sS https://getcomposer.org/installer | php 16 | sudo mv composer.phar /usr/local/bin/composer 17 | ``` 18 | 19 | - Download [EmitPHP source code](https://github.com/rnaga/EmitPHP.git) from github 20 | - Run composer to create autoload 21 | ```sh 22 | composer install 23 | ``` 24 | Now you can run [Examples](https://github.com/rnaga/EmitPHP/tree/master/examples) 25 | 26 | ## Usage 27 | ### WebSocket 28 | Yes, EmitPHP supports WebSocket. 29 | 30 | you can create your WebSocket Application with a few lines of code. 31 | 32 | Below is an example of how to create a WebSocket Application. 33 | 34 | ```php 35 | // Create a new WS Application 36 | $app = (new WSServer())->listen(4000)->app(); 37 | // Triggers when messages received 38 | $app->on('message', function($conn, $msg){ 39 | // Echo message 40 | $conn->send("echo => ". $msg); 41 | // Close the connection 42 | $conn->close(); 43 | }); 44 | 45 | \Emit\Loop(); 46 | ``` 47 | ### HTTP 48 | 49 | You can easily create a HTTP server as below 50 | ```php 51 | $server = (new HTTPServer())->listen(4000); 52 | $server->on('request', function($req, $res){ 53 | // Send response 54 | $res->send("Hello World"); 55 | // Close connection 56 | $res->end(); 57 | }); 58 | 59 | \Emit\Loop(); 60 | ``` 61 | ### Router 62 | Example for using Router 63 | 64 | ```php 65 | $server = (new HTTPServer())->listen(9000); 66 | // Create a new Route 67 | $route = $server->route(); 68 | // Get method 69 | $route->get("/", function($req, $res, $next){ 70 | $res->send("Hello World"); 71 | // Calling the next handler 72 | $next(); 73 | }); 74 | // Register the route 75 | $server->use($route); 76 | 77 | \Emit\Loop(); 78 | ``` 79 | ### FCGI 80 | EmitPHP supports FCGI which works with Web Servers such as apache 81 | ```php 82 | $server = (new FCGIServer())->listen(9000); 83 | $server->on('request', function($req, $res){ 84 | // Send response 85 | $res->send("Hello World"); 86 | // Close connection 87 | $res->end(); 88 | }); 89 | 90 | \Emit\Loop(); 91 | ``` 92 | 93 | See [examples](https://github.com/rnaga/EmitPHP/tree/master/examples) for more details. 94 | 95 | ## What's next 96 | 97 | Please send me your feeback at emitphp@gmail.com and let me know how you like it. 98 | If there are demands, I will work more. 99 | 100 | And if any of you wants to join the project, please let me know. 101 | 102 | ## License 103 | 104 | EmitPHP is licensed under the MIT license. See License File for more information. 105 | 106 | 107 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rnaga/emit-php", 3 | "description": "A PHP framework to develop WebSocket, HTTP and FCGI Applications", 4 | "license": "MIT", 5 | "keywords": ["websocket","http", "fcgi", "eventemitter"], 6 | "authors": [{ 7 | "name": "Ryohei Nagatsuka", 8 | "email": "ryoheinaga@gmail.com", 9 | "role": "Developer" 10 | }], 11 | "require": { 12 | "php": ">=7.0.0" 13 | }, 14 | "autoload": { 15 | "files": ["src/Loop.php"], 16 | "psr-4": { 17 | "Emit\\": "src/" 18 | } 19 | }, 20 | 21 | "autoload-dev": { 22 | "psr-4": { 23 | "EmitTest\\": "tests/" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/echo-server.php: -------------------------------------------------------------------------------- 1 | listen(4000); 12 | 13 | $server->on('accept', function($sever, $resource){ 14 | 15 | $remote = new ResourceEventEmitter(); 16 | 17 | $remote->on("read", function($remote, $resource) { 18 | 19 | // Receives data 20 | $data = StreamSocket::read($resource); 21 | 22 | // Close the connection if disconnected by the client 23 | if( is_null( $data ) ) 24 | { 25 | $remote->close(); 26 | return; 27 | } 28 | 29 | // Echoes data to the client 30 | StreamSocket::write($resource, "echo => " . $data); 31 | 32 | })->listenResource($resource); 33 | }); 34 | 35 | \Emit\Loop(); 36 | -------------------------------------------------------------------------------- /examples/fcgi.php: -------------------------------------------------------------------------------- 1 | listen(9000); 16 | 17 | $server->on('request', function($req, $res){ 18 | 19 | // Send response 20 | $res->send("Hello World"); 21 | 22 | // Close connection 23 | $res->end(); 24 | 25 | }); 26 | 27 | \Emit\Loop(); 28 | 29 | -------------------------------------------------------------------------------- /examples/http-cookie.php: -------------------------------------------------------------------------------- 1 | listen(4000); 10 | 11 | $route = $server->route(); 12 | 13 | // Parse cookie when requested 14 | $route->get([$server, 'cookieParser']); 15 | 16 | $route->get(function($req, $res){ 17 | 18 | // Get Cookies 19 | $cookie = $req->cookie; 20 | 21 | // Set Cookie1 22 | $res->cookie('key1', 1, ['path' => '/']); 23 | $res->cookie('key2', 2, ['path' => '/']); 24 | 25 | $res->send('Cookie => ' . print_r( $cookie, 1 ) ); 26 | $res->end(); 27 | 28 | }); 29 | 30 | $server->use($route); 31 | 32 | \Emit\Loop(); 33 | 34 | -------------------------------------------------------------------------------- /examples/http-rest.php: -------------------------------------------------------------------------------- 1 | listen(4000); 11 | 12 | // Create new Route 13 | $route = $server->route(); 14 | 15 | // Mapping route to /resource/:id, where :id is [0-9]+ 16 | $server->use(['/resource/:id', ['id' => '[0-9]+']], $route); 17 | 18 | // Create Resource 19 | $route->post(function($req, $res){ 20 | $res->send("Create resource for " . $req->params['id']); 21 | $res->end(); 22 | }); 23 | 24 | // Read Resource 25 | $route->get(function($req, $res){ 26 | $res->send("Read resource for " . $req->params['id']); 27 | $res->end(); 28 | }); 29 | 30 | // Update Resource 31 | $route->put(function($req, $res){ 32 | $res->send("Update resource for " . $req->params['id']); 33 | $res->end(); 34 | }); 35 | 36 | // Delete Resource 37 | $route->delete(function($req, $res){ 38 | $res->send("Delete resource for " . $req->params['id']); 39 | $res->end(); 40 | }); 41 | 42 | // 404 for all others 43 | $server->on('request', function($req, $res){ 44 | $res->status(404); 45 | $res->send('File not found'); 46 | $res->end(); 47 | }); 48 | 49 | \Emit\Loop(); 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/http-route-adavanced.php: -------------------------------------------------------------------------------- 1 | listen(4000); 12 | 13 | // Create new Route 14 | $route = $server->route(); 15 | 16 | // Path with regex. It matches as /abc/1234/def/ 17 | $regex = PathMatcher::regex('([a-z]+)/([0-9]+)/(.+)'); 18 | 19 | $route->get($regex, function($req, $res, $next){ 20 | 21 | // Get parameters 22 | $params = $req->params; 23 | 24 | $res->send("Regex => " . print_r($params, 1)); 25 | $res->end(); 26 | }); 27 | 28 | // Set parameters for 'id' and 'name' with regex 29 | $route->get(['/:id/:name', ['id' => '[0-9]+', 'name' => '[a-z]+']], function($req, $res, $next ){ 30 | 31 | // Get parmameters 32 | $params = $req->params; 33 | 34 | $res->send("Parameters => " . print_r( $params, 1)); 35 | $res->end(); 36 | }); 37 | 38 | // Easier way to set a parameter 39 | $route->get('/:any', function($req, $res, $next ){ 40 | // Get parmameters 41 | $params = $req->params; 42 | 43 | $res->send("Parameters => " . print_r( $params, 1)); 44 | $res->end(); 45 | }); 46 | 47 | // How to retrieve request in body 48 | $route->post(function($req, $res, $next){ 49 | 50 | $body = $req->body; 51 | 52 | // Parse request -- or use json_decode for json format 53 | parse_str($body, $query); 54 | 55 | $res->send("Body => " . print_r( $query, 1)); 56 | $res->end(); 57 | }); 58 | 59 | // 404 for all other requests 60 | $route->all(function($req, $res){ 61 | $res->status(404); 62 | $res->send(''); 63 | $res->end(); 64 | }); 65 | 66 | // Register the route 67 | $server->use($route); 68 | 69 | \Emit\Loop(); 70 | 71 | -------------------------------------------------------------------------------- /examples/http-route.php: -------------------------------------------------------------------------------- 1 | listen(4000); 11 | 12 | // Create new Route 13 | $route = $server->route(); 14 | 15 | // Get method 16 | $route->get("/", function($req, $res, $next){ 17 | $res->send("Hello World"); 18 | // Calling the next handler 19 | $next(); 20 | }); 21 | 22 | // Post method 23 | $route->post("/", function($req, $res ){ 24 | $res->send("Hello World"); 25 | $res->end(); 26 | }); 27 | 28 | // Matching /abcd 29 | $route->get("/abcd", function($req, $res ){ 30 | $res->send("/abcd"); 31 | $res->end(); 32 | }); 33 | 34 | // 404 for all other requests 35 | $route->all(function($req, $res){ 36 | $res->status(404); 37 | $res->end(); 38 | }); 39 | 40 | // Register route 41 | $server->use($route); 42 | 43 | \Emit\Loop(); 44 | 45 | -------------------------------------------------------------------------------- /examples/http.php: -------------------------------------------------------------------------------- 1 | listen(4000); 10 | 11 | $server->on('request', function($req, $res){ 12 | 13 | // Send response 14 | $res->send("Hello World"); 15 | 16 | // Close connection 17 | $res->end(); 18 | 19 | }); 20 | 21 | \Emit\Loop(); 22 | 23 | -------------------------------------------------------------------------------- /examples/timeout.php: -------------------------------------------------------------------------------- 1 | 10) 20 | // Out of the loop 21 | return false; 22 | 23 | echo "Loop " . ($i++) . " times\n"; 24 | return true; 25 | 26 | }, 1000); 27 | 28 | \Emit\Loop(); 29 | 30 | -------------------------------------------------------------------------------- /examples/ws-chat/html/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 |144 | | 145 | |