PHPackages                             glzjin/laravel-s - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. glzjin/laravel-s

ActiveLibrary[Framework](/categories/framework)

glzjin/laravel-s
================

🚀 LaravelS: Speed up Laravel/Lumen by Swoole, 'S' means Swoole, Speed, High performance.

v1.10.13(8y ago)018MITPHPPHP &gt;=5.5.9

Since Jan 19Pushed 8y ago1 watchersCompare

[ Source](https://github.com/glzjin/laravel-s)[ Packagist](https://packagist.org/packages/glzjin/laravel-s)[ Docs](https://github.com/hhxsv5/laravel-s)[ RSS](/packages/glzjin-laravel-s/feed)WikiDiscussions master Synced today

READMEChangelog (5)DependenciesVersions (120)Used By (0)

LaravelS - standing on the shoulders of giants
==============================================

[](#laravels---standing-on-the-shoulders-of-giants)

> 🚀 Speed up Laravel/Lumen by Swoole, 'S' means Swoole, Speed, High performance.

[![Latest Stable Version](https://camo.githubusercontent.com/b6512e9ed6b77cf281f3eb9961d6be32766cc4aee355e7088910ceccce892072/68747470733a2f2f706f7365722e707567782e6f72672f6868787376352f6c61726176656c2d732f762f737461626c652e737667)](https://packagist.org/packages/hhxsv5/laravel-s)[![Total Downloads](https://camo.githubusercontent.com/41c18f2e177c5d9e0ff14770a1a49a676f29e6f397438a8a015cbaf24309d389/68747470733a2f2f706f7365722e707567782e6f72672f6868787376352f6c61726176656c2d732f646f776e6c6f6164732e737667)](https://packagist.org/packages/hhxsv5/laravel-s)[![Latest Unstable Version](https://camo.githubusercontent.com/1986b657bb4f878a3ed36cf1614e0e9cb4adb7cdabf1418e2e5d79a7a28ede00/68747470733a2f2f706f7365722e707567782e6f72672f6868787376352f6c61726176656c2d732f762f756e737461626c652e737667)](https://packagist.org/packages/hhxsv5/laravel-s)[![License](https://camo.githubusercontent.com/08bc25d4e40d4de14d6d81497e69d310b50feda5f527bfbf18457abc8b37c995/68747470733a2f2f706f7365722e707567782e6f72672f6868787376352f6c61726176656c2d732f6c6963656e73652e737667)](https://github.com/hhxsv5/laravel-s/blob/master/LICENSE)[![Build Status](https://camo.githubusercontent.com/d319a764e12eb5d686a8bfb9337d74a856796375b9324d87234fb49db0504c4d/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6868787376352f6c61726176656c2d732f6261646765732f6275696c642e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/hhxsv5/laravel-s/build-status/master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/0350c9ef44db13587952520842f75b974adec240d567a726829cfb6a4c51534c/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6868787376352f6c61726176656c2d732f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/hhxsv5/laravel-s/?branch=master)[![Code Intelligence Status](https://camo.githubusercontent.com/6dd8f952fd69b1ff89082e693b8b57b4955fe126f561ef2dcef8602b21ba4fcf/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6868787376352f6c61726176656c2d732f6261646765732f636f64652d696e74656c6c6967656e63652e7376673f623d6d6173746572)](https://scrutinizer-ci.com/code-intelligence)

**[中文文档](https://github.com/hhxsv5/laravel-s/blob/master/README-CN.md)**

Features
--------

[](#features)

- High performance Swoole
- Built-in Http/[WebSocket](https://github.com/hhxsv5/laravel-s/blob/master/README.md#enable-websocket-server) server
- Memory resident
- [Asynchronous event listening](https://github.com/hhxsv5/laravel-s/blob/master/README.md#customized-asynchronous-events)
- [Asynchronous task queue](https://github.com/hhxsv5/laravel-s/blob/master/README.md#asynchronous-task-queue)
- [Millisecond cron job](https://github.com/hhxsv5/laravel-s/blob/master/README.md#millisecond-cron-job)
- Gracefully reload
- Automatically reload when code is modified
- Support Laravel/Lumen, good compatibility
- Simple &amp; Out of the box

Requirements
------------

[](#requirements)

DependencyRequirement[PHP](https://secure.php.net/manual/en/install.php)`>= 5.5.9`[Swoole](https://www.swoole.co.uk/)`>= 1.7.19` `The Newer The Better` `No longer support PHP5 since 2.0.12`[Laravel](https://laravel.com/)/[Lumen](https://lumen.laravel.com/)`>= 5.1`Gzip\[optional\][zlib](https://zlib.net/), be used to compress the HTTP response, check by *ldconfig -p|grep libz*Inotify\[optional\][inotify](http://pecl.php.net/package/inotify), be used to reload all worker processes when your code is modified, check by *php --ri inotify*Install
-------

[](#install)

1.Require package via [Composer](https://getcomposer.org/)([packagist](https://packagist.org/packages/hhxsv5/laravel-s)).

```
# Run in the root path of your Laravel/Lumen project.
composer require "hhxsv5/laravel-s:~1.0" -vvv
# Make sure that your composer.lock file is under the VCS
```

2.Add service provider.

- `Laravel`: in `config/app.php` file

```
'providers' => [
    //...
    Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class,
],
```

- `Lumen`: in `bootstrap/app.php` file

```
$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
```

3.Publish configuration.

> *Suggest that do publish after upgrade LaravelS every time*

```
php artisan laravels publish
```

`Special for Lumen`: you `DO NOT` need to load this configuration manually in `bootstrap/app.php` file, LaravelS will load it automatically.

```
// Unnecessary to call configure()
$app->configure('laravels');
```

4.Change `config/laravels.php`: listen\_ip, listen\_port, refer [Settings](https://github.com/hhxsv5/laravel-s/blob/master/Settings.md).

Run demo
--------

[](#run-demo)

> `php artisan laravels {start|stop|restart|reload|publish}`

CommandDescription`start`Start LaravelS, list the processes by *ps -ef|grep laravels*`stop`Stop LaravelS`restart`Restart LaravelS`reload`Reload all worker processes(Contain your business &amp; Laravel/Lumen codes), exclude master/manger process`publish`Publish configuration file `laravels.php` into folder `config`Cooperate with Nginx (Recommended)
----------------------------------

[](#cooperate-with-nginx-recommended)

```
gzip on;
gzip_min_length 1024;
gzip_comp_level 2;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
gzip_vary on;
gzip_disable "msie6";

upstream laravels {
    server 192.168.0.1:5200 weight=5 max_fails=3 fail_timeout=30s;
    #server 192.168.0.2:5200 weight=3 max_fails=3 fail_timeout=30s;
    #server 192.168.0.3:5200 backup;
}
server {
    listen 80;
    server_name laravels.com;
    root /xxxpath/laravel-s-test/public;
    access_log /yyypath/log/nginx/$server_name.access.log  main;
    autoindex off;
    index index.html index.htm;
    # Nginx handles the static resources(recommend enabling gzip), LaravelS handles the dynamic resource.
    location / {
        try_files $uri @laravels;
    }
    location @laravels {
        proxy_http_version 1.1;
        # proxy_connect_timeout 60s;
        # proxy_send_timeout 60s;
        # proxy_read_timeout 120s;
        proxy_set_header Connection "keep-alive";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Real-PORT $remote_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://laravels;
    }
}
```

Cooperate with Apache
---------------------

[](#cooperate-with-apache)

```
LoadModule proxy_module /yyypath/modules/mod_deflate.so

    SetOutputFilter DEFLATE
    DeflateCompressionLevel 2
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml

    ServerName www.laravels.com
    ServerAdmin hhxsv5@sina.com

    DocumentRoot /xxxpath/laravel-s-test/public;
    DirectoryIndex index.html index.htm

        AllowOverride None
        Require all granted

    LoadModule proxy_module /yyypath/modules/mod_proxy.so
    LoadModule proxy_module /yyypath/modules/mod_proxy_balancer.so
    LoadModule proxy_module /yyypath/modules/mod_lbmethod_byrequests.so.so
    LoadModule proxy_module /yyypath/modules/mod_proxy_http.so.so
    LoadModule proxy_module /yyypath/modules/mod_slotmem_shm.so
    LoadModule proxy_module /yyypath/modules/mod_rewrite.so

    ProxyRequests Off
    ProxyPreserveHost On

        BalancerMember http://192.168.1.1:8011 loadfactor=7
        #BalancerMember http://192.168.1.2:8011 loadfactor=3
        #BalancerMember http://192.168.1.3:8011 loadfactor=1 status=+H
        ProxySet lbmethod=byrequests

    #ProxyPass / balancer://laravels/
    #ProxyPassReverse / balancer://laravels/

    # Apache handles the static resources, LaravelS handles the dynamic resource.
    RewriteEngine On
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
    RewriteRule ^/(.*)$ balancer://laravels/%{REQUEST_URI} [P,L]

    ErrorLog ${APACHE_LOG_DIR}/www.laravels.com.error.log
    CustomLog ${APACHE_LOG_DIR}/www.laravels.com.access.log combined

```

Enable WebSocket server
-----------------------

[](#enable-websocket-server)

> The Listening address of WebSocket Sever is the same as Http Server.

1.Create WebSocket Handler class, and implement interface `WebsocketHandlerInterface`.

```
namespace App\Services;
use Hhxsv5\LaravelS\Swoole\WebsocketHandlerInterface;
/**
 * @see https://www.swoole.co.uk/docs/modules/swoole-websocket-server
 */
class WebsocketService implements WebsocketHandlerInterface
{
    // Declare constructor without parameters
    public function __construct()
    {
    }
    public function onOpen(\swoole_websocket_server $server, \swoole_http_request $request)
    {
        \Log::info('New Websocket connection', [$request->fd]);
        $server->push($request->fd, 'Welcome to LaravelS');
        // throw new \Exception('an exception');// all exceptions will be ignored, then record them into Swoole log, you need to try/catch them
    }
    public function onMessage(\swoole_websocket_server $server, \swoole_websocket_frame $frame)
    {
        \Log::info('Received message', [$frame->fd, $frame->data, $frame->opcode, $frame->finish]);
        $server->push($frame->fd, date('Y-m-d H:i:s'));
        // throw new \Exception('an exception');// all exceptions will be ignored, then record them into Swoole log, you need to try/catch them
    }
    public function onClose(\swoole_websocket_server $server, $fd, $reactorId)
    {
        // throw new \Exception('an exception');// all exceptions will be ignored, then record them into Swoole log, you need to try/catch them
    }
}
```

2.Modify `config/laravels.php`.

```
// ...
'websocket'      => [
    'enable'  => true,
    'handler' => \App\Services\WebsocketService::class,
],
'swoole'         => [
    //...
    // Must set dispatch_mode in (2, 4, 5), see https://www.swoole.co.uk/docs/modules/swoole-server/configuration
    'dispatch_mode' => 2,
    //...
],
// ...
```

3.Use `swoole_table` to bind FD &amp; UserId, optional, [Swoole Table Demo](https://github.com/hhxsv5/laravel-s/blob/master/README.md#use-swoole_table). Also you can use the other global storage services, like Redis/Memcached/MySQL, but be careful that FD will be possible conflicting between multiple `Swoole Servers`.

4.Cooperate with Nginx (Recommended)

> Refer [WebSocket Proxy](http://nginx.org/en/docs/http/websocket.html)

```
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream laravels-ws {
    server 192.168.0.1:5200 weight=5 max_fails=3 fail_timeout=30s;
    #server 192.168.0.2:5200 weight=3 max_fails=3 fail_timeout=30s;
    #server 192.168.0.3:5200 backup;
}

server {
    listen 80;
    server_name laravels-ws.com;
    root /xxxpath/laravel-s-test/public;
    access_log /yyypath/log/nginx/$server_name.access.log  main;
    autoindex off;
    index index.html index.htm;
    # Nginx handles the static resources(recommend enabling gzip), LaravelS handles the dynamic resource.
    location / {
        try_files $uri @laravels;
    }
    location @laravels {
        proxy_http_version 1.1;
        # proxy_connect_timeout 60s;
        # proxy_send_timeout 60s;
        # proxy_read_timeout: Nginx will close the connection if client does not send data to server in 60 seconds; At the same time, this close behavior is also affected by heartbeat setting of Swoole
        # proxy_read_timeout 60s;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Real-PORT $remote_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_pass http://laravels-ws;
    }
}
```

Listen events
-------------

[](#listen-events)

### System events

[](#system-events)

> Usually, you can reset/destroy some `global/static` variables, or change the current `Request/Response` object.

- `laravels.received_request` After LaravelS parsed `swoole_http_request` to `Illuminate\Http\Request`, before Laravel's Kernel handles this request.

```
// Edit file `app/Providers/EventServiceProvider.php`, add the following code into method `boot`
// If no variable $events, you can also call Facade \Event::listen().
$events->listen('laravels.received_request', function (\Illuminate\Http\Request $req, $app) {
    $req->query->set('get_key', 'hhxsv5');// Change query of request
    $req->request->set('post_key', 'hhxsv5'); // Change post of request
});
```

- `laravels.generated_response` After Laravel's Kernel handled the request, before LaravelS parses `Illuminate\Http\Response` to `swoole_http_response`.

```
// Edit file `app/Providers/EventServiceProvider.php`, add the following code into method `boot`
// If no variable $events, you can also call Facade \Event::listen().
$events->listen('laravels.generated_response', function (\Illuminate\Http\Request $req, \Symfony\Component\HttpFoundation\Response $rsp, $app) {
    $rsp->headers->set('header-key', 'hhxsv5');// Change header of response
});
```

### Customized asynchronous events

[](#customized-asynchronous-events)

> This feature depends on `AsyncTask` of `Swoole`, your need to set `swoole.task_worker_num` in `config/laravels.php` firstly. The performance of asynchronous event processing is influenced by number of Swoole task process, you need to set [task\_worker\_num](https://www.swoole.co.uk/docs/modules/swoole-server/configuration) appropriately.

1.Create event class.

```
use Hhxsv5\LaravelS\Swoole\Task\Event;
class TestEvent extends Event
{
    private $data;
    public function __construct($data)
    {
        $this->data = $data;
    }
    public function getData()
    {
        return $this->data;
    }
}
```

2.Create listener class.

```
use Hhxsv5\LaravelS\Swoole\Task\Event;
use Hhxsv5\LaravelS\Swoole\Task\Listener;
class TestListener1 extends Listener
{
    // Declare constructor without parameters
    public function __construct()
    {
    }
    public function handle(Event $event)
    {
        \Log::info(__CLASS__ . ':handle start', [$event->getData()]);
        sleep(2);// Simulate the slow codes
        // throw new \Exception('an exception');// all exceptions will be ignored, then record them into Swoole log, you need to try/catch them
    }
}
```

3.Bind event &amp; listeners.

```
// Bind event & listeners in file "config/laravels.php", one event => many listeners
[
    // ...
    'events' => [
        \App\Tasks\TestEvent::class => [
            \App\Tasks\TestListener1::class,
            //\App\Tasks\TestListener2::class,
        ],
    ],
    // ...
];
```

4.Fire event.

```
// Create instance of event and fire it, "fire" is asynchronous.
use Hhxsv5\LaravelS\Swoole\Task\Event;
$success = Event::fire(new TestEvent('event data'));
var_dump($success);// Return true if sucess, otherwise false
```

Asynchronous task queue
-----------------------

[](#asynchronous-task-queue)

> This feature depends on `AsyncTask` of `Swoole`, your need to set `swoole.task_worker_num` in `config/laravels.php` firstly. The performance of task processing is influenced by number of Swoole task process, you need to set [task\_worker\_num](https://www.swoole.co.uk/docs/modules/swoole-server/configuration) appropriately.

1.Create task class.

```
use Hhxsv5\LaravelS\Swoole\Task\Task;
class TestTask extends Task
{
    private $data;
    private $result;
    public function __construct($data)
    {
        $this->data = $data;
    }
    // The logic of task handling, run in task process, CAN NOT deliver task
    public function handle()
    {
        \Log::info(__CLASS__ . ':handle start', [$this->data]);
        sleep(2);// Simulate the slow codes
        // throw new \Exception('an exception');// all exceptions will be ignored, then record them into Swoole log, you need to try/catch them
        $this->result = 'the result of ' . $this->data;
    }
    // Optional, finish event, the logic of after task handling, run in worker process, CAN deliver task
    public function finish()
    {
        \Log::info(__CLASS__ . ':finish start', [$this->result]);
        Task::deliver(new TestTask2('task2 data')); // Deliver the other task
    }
}
```

2.Deliver task.

```
// Create instance of TestTask and deliver it, "deliver" is asynchronous.
use Hhxsv5\LaravelS\Swoole\Task\Task;
$task = new TestTask('task data');
// $task->delay(3);// delay 3 seconds to deliver task
$ret = Task::deliver($task);
var_dump($ret);// Return true if sucess, otherwise false
```

Millisecond cron job
--------------------

[](#millisecond-cron-job)

> Wrapper cron job base on [Swoole's Millisecond Timer](https://www.swoole.co.uk/docs/modules/swoole-async-io), replace `Linux` `Crontab`.

1.Create cron job class.

```
namespace App\Jobs\Timer;
use Hhxsv5\LaravelS\Swoole\Timer\CronJob;
class TestCronJob extends CronJob
{
    protected $i = 0;
    // Declare constructor without parameters
    public function __construct()
    {
    }
    public function interval()
    {
        return 1000;// Run every 1000ms
    }
    public function run()
    {
        \Log::info(__METHOD__, ['start', $this->i, microtime(true)]);
        // do something
        $this->i++;
        \Log::info(__METHOD__, ['end', $this->i, microtime(true)]);

        if ($this->i >= 10) { // run 10 times only
            \Log::info(__METHOD__, ['stop', $this->i, microtime(true)]);
            $this->stop(); // stop this cron job
        }
        // throw new \Exception('an exception');// all exceptions will be ignored, then record them into Swoole log, you need to try/catch them
    }
}
```

2.bind cron job.

```
// Bind cron jobs in file "config/laravels.php"
[
    // ...
    'timer'          => [
        'enable' => true, // Enable Timer
        'jobs'   => [ // the list of cron job
            // Enable LaravelScheduleJob to run `php artisan schedule:run` every 1 minute, replace Linux Crontab
            //\Hhxsv5\LaravelS\Illuminate\LaravelScheduleJob::class,
            \App\Jobs\Timer\TestCronJob::class,
        ],
    ],
    // ...
];
```

Get the instance of `swoole_server` in your project
---------------------------------------------------

[](#get-the-instance-of-swoole_server-in-your-project)

```
/**
 * $swoole is the instance of `swoole_websocket_server` if enable websocket server, otherwise `\swoole_http_server`
 * @var \swoole_http_server|\swoole_websocket_server $swoole
 */
$swoole = app('swoole');
var_dump($swoole->stats());// Singleton
```

Use `swoole_table`
------------------

[](#use-swoole_table)

1.Define `swoole_table`, support multiple.

> All defined tables will be created before Swoole starting.

```
// in file "config/laravels.php"
[
    // ...
    'swoole_tables'  => [
        // Scene：bind UserId & FD in WebSocket
        'ws' => [// The Key is table name, will add suffix "Table" to avoid naming conficts. Here defined a table named "wsTable"
            'size'   => 102400,// The max size
            'column' => [// Define the columns
                ['name' => 'value', 'type' => \swoole_table::TYPE_INT, 'size' => 8],
            ],
        ],
        //...Define the other tables
    ],
    // ...
];
```

2.Access `swoole_table`: all table instances will be bound on `swoole_server`, access by `app('swoole')->xxxTable`.

```
// Scene：bind UserId & FD in WebSocket
public function onOpen(\swoole_websocket_server $server, \swoole_http_request $request)
{
    // var_dump(app('swoole') === $server);// The same instance
    $userId = mt_rand(1000, 10000);
    app('swoole')->wsTable->set('uid:' . $userId, ['value' => $request->fd]);// Bind map uid to fd
    app('swoole')->wsTable->set('fd:' . $request->fd, ['value' => $userId]);// Bind map fd to uid
    $server->push($request->fd, 'Welcome to LaravelS');
}
public function onMessage(\swoole_websocket_server $server, \swoole_websocket_frame $frame)
{
    foreach (app('swoole')->wsTable as $key => $row) {
        if (strpos($key, 'uid:') === 0) {
            $server->push($row['value'], 'Broadcast: ' . date('Y-m-d H:i:s'));// Broadcast
        }
    }
}
public function onClose(\swoole_websocket_server $server, $fd, $reactorId)
{
    $uid = app('swoole')->wsTable->get('fd:' . $fd);
    if ($uid !== false) {
        app('swoole')->wsTable->del('uid:' . $uid['value']); // Ubind uid map
    }
    app('swoole')->wsTable->del('fd:' . $fd);// Unbind fd map
    $server->push($fd, 'Goodbye');
}
```

Important notices
-----------------

[](#important-notices)

- Get all info of request from `Illuminate\Http\Request` Object, compatible with $\_SERVER/$\_ENV/$\_GET/$\_POST/$\_FILES/$\_COOKIE/$\_REQUEST, `CANNOT USE` $\_SESSION.

```
public function form(\Illuminate\Http\Request $request)
{
    $name = $request->input('name');
    $all = $request->all();
    $sessionId = $request->cookie('sessionId');
    $photo = $request->file('photo');
    $rawContent = $request->getContent();
    //...
}
```

- Respond by `Illuminate\Http\Response` Object, compatible with echo/vardump()/print\_r()，`CANNOT USE` functions like header()/setcookie()/http\_response\_code().

```
public function json()
{
    return response()->json(['time' => time()])->header('header1', 'value1')->withCookie('c1', 'v1');
}
```

- `global`, `static` variables which you declared are need to destroy(reset) manually.
- Infinitely appending element into `static`/`global` variable will lead to memory leak.

```
// Some class
class Test
{
    public static $array = [];
    public static $string = '';
}

// Controller
public function test(Request $req)
{
    // Memory leak
    Test::$array[] = $req->input('param1');
    Test::$string .= $req->input('param2');
}
```

[Known compatible issues](https://github.com/hhxsv5/laravel-s/blob/master/KnownCompatibleIssues.md)
---------------------------------------------------------------------------------------------------

[](#known-compatible-issues)

Todo list
---------

[](#todo-list)

1. Connection pool for MySQL/Redis.
2. Wrap coroutine clients for MySQL/Redis/Http.

License
-------

[](#license)

[MIT](https://github.com/hhxsv5/laravel-s/blob/master/LICENSE)

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity75

Established project with proven stability

 Bus Factor1

Top contributor holds 97% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

115

Last Release

2947d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ac03f7386f8431f560feed39457d4cb59c7a11f7fe3c7b05d300521edb776c43?d=identicon)[glzjin](/maintainers/glzjin)

---

Top Contributors

[![hhxsv5](https://avatars.githubusercontent.com/u/7278743?v=4)](https://github.com/hhxsv5 "hhxsv5 (450 commits)")[![glzjin](https://avatars.githubusercontent.com/u/7975407?v=4)](https://github.com/glzjin "glzjin (10 commits)")[![m01i0ng](https://avatars.githubusercontent.com/u/19723234?v=4)](https://github.com/m01i0ng "m01i0ng (2 commits)")[![bluebellx7](https://avatars.githubusercontent.com/u/9065896?v=4)](https://github.com/bluebellx7 "bluebellx7 (1 commits)")[![shenstef](https://avatars.githubusercontent.com/u/5144202?v=4)](https://github.com/shenstef "shenstef (1 commits)")

---

Tags

http serverswoolecoroutinewebsocket serverhigh-performanceasync eventLaravelSasync taskinotify reloadmemory resident

### Embed Badge

![Health badge](/badges/glzjin-laravel-s/health.svg)

```
[![Health](https://phpackages.com/badges/glzjin-laravel-s/health.svg)](https://phpackages.com/packages/glzjin-laravel-s)
```

###  Alternatives

[laravel/octane

Supercharge your Laravel application's performance.

4.0k21.5M159](/packages/laravel-octane)[hhxsv5/laravel-s

🚀 LaravelS is an out-of-the-box adapter between Laravel/Lumen and Swoole.

3.9k676.0k10](/packages/hhxsv5-laravel-s)[mix/mix

PHP CLI mode development framework

1.9k1.2k](/packages/mix-mix)[luoxiaojun/sw-fw-less

Swoole Http Server without framework

165.3k](/packages/luoxiaojun-sw-fw-less)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
