{"id":13669186,"url":"https://github.com/scil/LaravelFly","last_synced_at":"2025-04-27T01:32:50.667Z","repository":{"id":62541231,"uuid":"43991258","full_name":"scil/LaravelFly","owner":"scil","description":"To be an absolutely safe solution to speed up Laravel with Swoole. Preloading + Coroutine and Tinker Online.","archived":true,"fork":false,"pushed_at":"2024-10-17T00:41:16.000Z","size":1240,"stargazers_count":457,"open_issues_count":1,"forks_count":41,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-01-01T04:32:26.122Z","etag":null,"topics":["laravel","speed","swoole","tinker"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scil.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.996ICU.en.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-10-10T03:02:04.000Z","updated_at":"2024-10-17T00:41:58.000Z","dependencies_parsed_at":"2024-11-11T05:31:56.153Z","dependency_job_id":"e591df15-172c-457f-b9b2-7bc73bd15d77","html_url":"https://github.com/scil/LaravelFly","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scil%2FLaravelFly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scil%2FLaravelFly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scil%2FLaravelFly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scil%2FLaravelFly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scil","download_url":"https://codeload.github.com/scil/LaravelFly/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251077102,"owners_count":21532607,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","speed","swoole","tinker"],"created_at":"2024-08-02T08:01:05.457Z","updated_at":"2025-04-27T01:32:45.652Z","avatar_url":"https://github.com/scil.png","language":"PHP","funding_links":[],"categories":["PHP","Framework Integration","目录","框架( Frameworks )"],"sub_categories":["框架 frameworks"],"readme":"\nPlease refer to [Swoole handles multiple requests simultaneously per-worker](https://github.com/nextcloud/server/issues/36290#issuecomment-1555965453)  and [Hola FrankenPHP! Laravel Octane Servers Comparison](https://medium.com/beyn-technology/hola-frankenphp-laravel-octane-servers-comparison-pushing-the-boundaries-of-performance-d3e7ad8e652c)  \n\n====\n\nWould you like php 7.4 Preloading? Would you like php coroutine? Today you can use them with Laravel  because of Swoole. With LaravalFly, Laravel will begin like Django 3.0  to be fully async-capable.\n\nLaravelFly is a safe solution to speeds up new or old Laravel 5.5+ projects, with preloading and coroutine, while without data pollution or memory leak. And it makes Tinker available online (use tinker while Laravel is responding requests from browsers).\n\nThanks to [Laravel](http://laravel.com/), [Swoole](https://github.com/swoole/swoole-src) and [PsySh](https://github.com/bobthecow/psysh).\n\n**Notice**: Great News! [Laravel is supporting Swoole offcially with  laravel/octane!](https://github.com/laravel/octane)\n\n## A simple ab test \n\n`ab -k -n 1000 -c 10 http://zc.test` (21 sql statements were executed in single request)\n\n.   | fpm  | Fly\n------------ | ------------ | ------------- \nTime taken ≈ | 43.5 s  | 12.3 s\nRequests per second   | 23    | 81.5\n  50%  | 303 ms  | 117 ms\n  80%  | 360 ms  | 153 ms\n  99%  | 1341 ms | 239 ms\n\n\u003cdetails\u003e\n\u003csummary\u003eTest Env\u003c/summary\u003e\n\u003cdiv\u003e\n\n\n* env:   \n  - ubuntu 16.04 on VirtualBox ( 1 CPU: i7-7700HQ 2.80GHz ; Memory: 2G  )  \n  - php7.2 + opcache + 5 workers for both fpm and laravelfly ( phpfpm : pm=static  pm.max_children=5)\n  - connection pool and coroutine mysql\n* Test date : 2018/10\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n## Version Compatibility\n\n- Laravel 5.5 ~ 6.0\n- Swoole \u003e4.2.13\n\n## Quick Start\n\n1.`pecl install swoole`   \nMake sure `extension=swoole.so` in config file for php cli, not for fpm.   \nSuggest: `pecl install inotify`   \n\n2.`composer require \"scil/laravel-fly\":\"dev-master\"`\n\n3.`php vendor/scil/laravel-fly/bin/fly start`   \nIf you enable `eval(tinker())` and see an error about mkdir, you can start LaravelFly with sudo.\n\nNow, your project is flying and listening to port 9501. Enjoy yourself.\n\n## Docker-compose\n\n```\ncomposer require \"scil/laravel-fly\":\"dev-master\"\n\nphp artisan vendor:publish --tag=fly-server\n\n# 127.0.0.1:8080\n# you can edit this docker-compos file and use your own nginx conf\ndocker-compose -f vendor/scil/laravel-fly-local/docker/docker-compose.yml up -d\n```\n\n## Doc\n\n[Configuration](https://github.com/scil/LaravelFly/wiki/Configuration)\n\n[Commands: Start, Reload \u0026 Debug](https://github.com/scil/LaravelFly/wiki/Commands)\n\n[Coding Guideline](https://github.com/scil/LaravelFly/wiki/Coding-Requirement)\n\n[Events about LaravelFly](doc/events.md)\n\n[Using tinker when Laravel Working](doc/tinker.md)\n\n[For Dev](doc/dev.md)\n\n## Recommended Packages\n\n- [swlib/saber](https://github.com/swlib/saber/blob/master/README-EN.md)  Coroutine HTTP client, based on `Swoole\\Coroutine\\Http\\Client`.   \nBrowser-like cookie managment, multiple requests concurrent, request/response interceptors and so on.  \nTo ensure safety, set `const LARAVELFLY_COROUTINE = true;` in fly.conf.php.\n\n\n## Features and Behaviors\n\n- Same codes can run on PHP-FPM or LaravelFly. LaravelFly can be installed on your existing projects without affecting nginx/apache server, that's to say, you can run LaravelFly server and nginx/apache server simultaneously to run the same laravel project. The nginx conf [swoole_fallback_to_phpfpm.conf](config/swoole_fallback_to_phpfpm.conf) allow you use LaravelFlyServer as the primary server, and the phpfpm as a backup server which will be passed requests when the LaravelFlyServer is unavailable. Another nginx conf [use_swoole_or_fpm_depending_on_clients](config/use_swoole_or_fpm_depending_on_clients.conf) allows us use query string `?useserver=\u003cswoole|fpm|...` to select the server between swoole or fpm. That's wonderful for test, such as to use eval(tinker()) as a online debugger for your fpm-supported projects. Apache? There is a example [Cooperate with Apache](https://github.com/hhxsv5/laravel-s#cooperate-with-apache) from laravel-s.\n\n- Moderate strategy: by default, each Third Party service provider is registered on server worker process (before the first request arrived at server) , booted in request.\n\n- By default, all Laravel official services are COROUTINE-FRIENDLY, including mysql and redis. You can make a service or object before any requests. There are two ways:\n  - let the service or object live in multiple requests (only one instance of the service). LaravelFly named it  **WORKER SERVICE**, **WORKER OBJECT** or **COROUTINE-FRIENDLY SERVICE/OBJECT**.\n  - cloned the service or object in each request (one instance in one request).LaravelFly named it **CLONE SERVICE** or **CLONE OBJECT**. This way is simple, but often has the problem [Stale Reference](https://github.com/scil/LaravelFly/wiki/clone-and-Stale-Reference). This type is used widely by [laravel-swoole](https://github.com/swooletw/laravel-swoole) and [laravel-s](https://github.com/hhxsv5/laravel-s),  while used rarely by LaravelFly.\n  \n- Extra speed improvements such as connection pool, middlewares cache, view path cache.\n\n- Check server info at /laravel-fly/info. (This feture is under dev and more infomations will be available.)\n\n- No support for static files any more, so use it with other servers. Conf examples: [nginx](https://github.com/scil/LaravelFly/#laravelfly-usability) or [Apache](https://github.com/hhxsv5/laravel-s#cooperate-with-apache)\n\n- [swoole-job](https://github.com/scil/LaravelFly/wiki/Configuration#run-jobs-or-listeners-in-swoole-tasks),A Laravel job or event listener can be delivered into a swoole task process and executed at once `artisan queue:work` needless any more.\n\n- `exit()` or `die()` in an route action would output content to console or swoole log, and not make server die or reload. If you would like to change that behavior, fork LaravalFly and catch `\\Swoole\\ExitException` in  `LaravelFly\\Map\\Kernel::handle`.\n\n- Support connection pool. There's only one connection available in each request.But if you use `fly()` or `fly2()`, you can use connections more than one.\n\n- functions `fly()` and `fly2()` which are like `go()` provided by [golang](https://github.com/golang/go) or [swoole](https://github.com/swoole/swoole-src), plus Laravel services can be used in `fly()` and `fly2()` without closure.  The `fly2()` has the limited ability to change services in current request, e.g. registering a new event handler for current request. `fly2()` is not suggested. \n\nA coroutine starting in a request, can still live when the request ends. What's the effect of following route?    \nIt responds with 'coroutine1; outer1; coroutine2; outer2; outer3',   \nbut it write log 'coroutine1; outer1; coroutine2; outer2; outer3; coroutine2.end; coroutine1.end'\n``` \n// ensure ` const LARAVELFLY_COROUTINE = true;` in fly.conf.php\n\nRoute::get('/fly', function () {\n\n    $a = [];\n    \n    fly(function () use (\u0026$a) {\n    \n        $a[] = 'coroutine1';\n        \\co::sleep(2);\n        $a[] = 'coroutine1.end';\n        \\Log::info(implode('; ', $a));\n        \n        // Eloquent can be used even if current request has ended.\n        // $user = new User();\n        // $user-\u003ename = implode('; ',$a);\n        // $user-\u003esave();\n        \n    });\n\n    $a[] = 'outer1';\n    \n\n    // go() can use laravel service  with closure\n    $log = app('log');\n    go(function () use (\u0026$a, $log) {\n        $a[] = 'coroutine2';\n        \\co::sleep(1.2);\n        $a[] = 'coroutine2.end';\n    });\n\n    $a[] = 'outer2';\n\n    \\co::sleep(1);\n\n    $a[] = 'outer3';\n\n    return implode(';', $a);\n\n});\n```\n\n\n\n## Similar projects that mix swoole and laravel\n\nThe main distinguishing feature of LaravalFly is refactoring Laravel, like what Django 3.0 does.\n\n### 1. [laravel-swoole](https://github.com/swooletw/laravel-swoole) \n\nIt is alse a safe sollution. It has supported Lumen and websocket. Its doc is great and also useful for LaravelFly.   \n\nThe main difference is that in laravel-swoole user's code will be processed by a new `app` cloned from SwooleTW\\Http\\Server\\Application::$application and laravel-swoole updates related container bindings to the new app. However in LaravelFly, the sandbox is not a new app, but an item in the $corDict of the unique application container.   \nIn LaravelFly, most other objects such as `app`, `event`.... always keep one object in a worker process, `clone` is not used at all by default. LaravelFly makes most of laravel objects keep safe on their own. It's about high cohesion \u0026 low coupling and the granularity is at the level of app container or services/objects. For users of laravel-swoole, it's a big challenge to handle the relations of multiple packages and objects which to be booted before any requests. Read [Stale Reference](https://github.com/scil/LaravelFly/wiki/clone-and-Stale-Reference). \n\n .  | technique | work to maintaining relations of cloned objects to avoid Stale Reference \n------------ |------------ | ------------ \nlaravel-swoole  | clone app contaniner and objects to make them safe | more work (as app,event...are cloned)\nLaravelFly Mode Map |  refactor most official objects to make them safe on their own | few work ( nothing is cloned by default)\n\nIn LaravelFly, another benefit of non-cloned objects is allowing some improvements, such as event listeners cache, route middlewares cache.\n\n### 2. [laravel-s](https://github.com/hhxsv5/laravel-s)\n\nMany great features!\n\nAbout data pollution? Same technique and problems as laravel-swoole. And neither support coroutine jumping (from one request to another request). \n\n\n## Todo About Improvement\n\n- [x] Pre-include. Server configs 'pre_include' and 'pre_files'.\n- [x] Server config 'early_laravel'\n- [x] Cache for LaravelFly app config. laravelfly_ps_map.php or laravelfly_ps_simple.php located bootstrap/cache\n- [x] Cache for Log. Server options 'log_cache'.\n- [x] Watching maintenance mode using swoole_event_add. No need to check file storage/framework/down in every request.\n- [x] Cache for kernel middlewares objects. Kernel::getParsedKernelMiddlewares, only when LARAVELFLY_SERVICES['kernel'] is true.\n- [x] Cache for route middlewares. $cacheByRoute in Router::gatherRouteMiddleware, only useful when all route middleaes are reg on worker.\n- [x] Cache for route middlewares objects. config('laravelfly.singleton_route_middlewares') and $cacheForObj in Router::gatherRouteMiddleware, avoid creating instances repeatly.\n- [x] Cache for terminateMiddleware objects.\n- [x] Cache for event listeners. $listenersStalbe in LaravelFly\\Map\\IlluminateBase\\Dispatcher\n- [x] Cache for view compiled path. LARAVELFLY_SERVICES['view.finder'] or  App config 'view_compile_1'\n- [x] Mysql coroutine. Old code dropped, laravel-s used.\n- [x] db connection pool and redis connection pool. In `fly()` or `fly2()`, connections to be used would be fetched from pool, not inherit the same connections from request coroutine. code: `$this-\u003econnections[$childId] = [];` in ConnectionsTrait.php\n- [x] swoole redis driver\n- [ ] swoole redis driver: how to use `errMsg` `errCode`\n- [ ] use [hyperf/database](https://github.com/hyperf/database) to replace official version?\n- [ ] use [swlib/swpdo](https://github.com/swlib/swpdo) to replace SwoolePDO?\n- [ ] Cache for HasRelationships. disable and experimental, not ready\n- [x] Cache for RouteDependencyResolverTrait \n- [ ] Converting between swoole request/response and Laravel Request/Response\n- [ ] safe: auth, remove some props?\n- [ ] use: https://github.com/louislivi/smproxy\n- [ ] use: https://github.com/kcloze/swoole-jobs or https://github.com/osgochina/Donkey\n\n## Other Todo\n\n- [x] add events\n- [x] watch code changes and hot reload\n- [x] supply server info. default url is: /laravel-fly/info\n- [x] function fly()\n- [x] job executed in task process. Related: vendor\\scil\\laravel-fly-files-local\\src\\Foundation\\Bus\\\n- [x] event listeners executed in task process. Related: LaravelFly\\Map\\IlluminateBase\\Dispatcher and vendor\\scil\\laravel-fly-files\\src\\Foundation\\Support\\Providers\\EventServiceProvider.php\n- [ ] use $this-\u003eoutput instead of echo() in Common.php\n- [ ] bootstrap all service providers in task process\n- [ ] try ocramius/generated-hydrator for laravel-fly/info when its version 3 is ready (it will require nikic/php-parser v4 which is needed by others)  // or Zend\\Hydrator\\Reflection?\n- [ ] add tests about auth SessionGuard: Illuminate/Auth/SessionGuard.php with uses Request::createFromGlobals\n- [ ] add tests about uploaded file, related symfony/http-foundation files: File/UploadedFile.php  and FileBag.php(fixPhpFilesArray)\n- [ ] websocket\n- [ ] send file\n- [ ] travis, static analyze like phan, phpstan or https://github.com/exakat/php-static-analysis-tools\n- [ ] cache fly\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscil%2FLaravelFly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscil%2FLaravelFly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscil%2FLaravelFly/lists"}