Swoole It is an excellent PHP extension, which can realize the resident service and asynchrony that native PHP is difficult to achieve. Just in time, I had a project on Laravel that I could toss about, so I studied it.
Laravel project is based on composer, so I post the require declaration in my composer.json:
{ "require": { "php": "^7.1.3", "cybercog/laravel-love": "^5.1", "dingo/api": "~v2.0.0-alpha2", "doctrine/dbal": "^2.8", "fideloper/proxy": "^4.0", "guzzlehttp/guzzle": "^6.3", "infyomlabs/adminlte-templates": "5.6.x-dev", "infyomlabs/laravel-generator": "5.6.x-dev", "jeroennoten/laravel-adminlte": "^1.23", "laravel/framework": "5.6.*", "laravel/tinker": "^1.0", "laravelcollective/html": "^5.6.0", "lshorz/luocaptcha": "^1.0", "overtrue/laravel-lang": "v3.0.08", "overtrue/laravel-wechat": "^4.0", "predis/predis": "^1.1", "spatie/laravel-permission": "^2.17", "tymon/jwt-auth": "~1.0.0-rc.2", "yajra/laravel-datatables-buttons": "^4.0", "yajra/laravel-datatables-oracle": "^8.7" } }
If we want to open swoole, these are the optional packages:
But generally speaking, the services that need to be resident in the container in the project are not the same as those that need to be rebuilt every time, so I'm on the wrong side.
start
We need to replace public/index.php with the following
<?php use Illuminate\Http\Request; use Illuminate\Http\Response; define('LARAVEL_START', microtime(true)); require __DIR__ . '/../vendor/autoload.php'; $app = require_once __DIR__ . '/../bootstrap/app.php'; class Laravel { /** * Illuminate\Foundation\Application * * @var \Illuminate\Foundation\Application */ public $app; /** * App\Http\Kernel * * @var \App\Http\Kernel */ public $kernel; /** * App\Http\Requests\Request * * @var \App\Http\Requests\Request */ public $request; /** * Illuminate\Http\JsonResponse * * @var \Illuminate\Http\JsonResponse */ public $response; /** * structure * * @param \Illuminate\Foundation\Application $app */ public function __construct(\Illuminate\Foundation\Application $app) { $this->app = $app; } /** * RUN * * @return void */ public function run() { \Swoole\Runtime::enableCoroutine(true); $http = new swoole_http_server('127.0.0.1', '80'); $http->set([ 'document_root' => public_path('/'), 'enable_static_handler' => true, ]); $http->on('request', function ($req, $res) { try { $kernel = $this->app->make(Illuminate\Contracts\Http\Kernel::class); $get = $req->get ?? []; $post = $req->post ?? []; $input = array_merge($get, $post); $cookie = $req->cookie ?? []; $files = $req->files ?? []; $server = $req->server ?? []; $request = Request::create($req->server['request_uri'], $req->server['request_method'], $input, $cookie, $files, $server); if (isset($req->header['x-requested-with']) && $req->header['x-requested-with'] == "XMLHttpRequest") { $request->headers->set('X-Requested-With', "XMLHttpRequest", true); } if (isset($req->header['accept']) && $req->header['accept']) { $request->headers->set('Accept', $req->header['accept'], true); } $response = $kernel->handle($request); $res->status($response->getStatusCode()); foreach ($response->headers->allPreserveCaseWithoutCookies() as $name => $values) { foreach ($values as $value) { $res->header($name, $value, false); } } foreach ($response->headers->getCookies() as $cookie) { $res->header('Set-Cookie', $cookie->getName() . strstr($cookie, '='), false); } dump(time()); $res->end($response->getContent()); $this->app->forgetInstance('request'); } catch (\throwable $e) { echo $e->getMessage(); echo PHP_EOL; echo $e->getFile(); echo PHP_EOL; echo $e->getLine(); echo PHP_EOL; } }); $http->start(); } } (new Laravel($app))->run();
It is found that most of the pages are OK at runtime. Only a few list pages generated by infyomlabs / laravel generator are used. When AJAX pulls JSON, it returns HTML.
Troubleshooting
In the controller code of the problem page, find the following
/** * Display a listing of the Star. * * @param StarDataTable $starDataTable * @return Response */ public function index(StarDataTable $starDataTable) { return $starDataTable->render('stars.index'); } //Location StarDataTable::render() arrived /** * Process dataTables needed render output. * * @param string $view * @param array $data * @param array $mergeData * @return mixed */ public function render($view, $data = [], $mergeData = []) { if ($this->request()->ajax() && $this->request()->wantsJson()) { return app()->call([$this, 'ajax']); } ... }
This is to determine whether $this - > request() is an XHR request, and the Accept request header declares application/json
And $this - > request() is implemented as follows
/** * Get DataTables Request instance. * * @return \Yajra\DataTables\Utilities\Request */ public function request() { return $this->request ?: $this->request = resolve('datatables.request'); }
It's not hard to see that if you build for the first time, you will
$this->request = resolve('datatables.request');
What is the implementation of resolve?
if (! function_exists('resolve')) { /** * Resolve a service from the container. * * @param string $name * @return mixed */ function resolve($name) { return app($name); } }
This is the process of getting datatables.request from the container.
So we just need to let each request end and the $app container forget about datatables.request
Improvement
Add forgotten datatables.request
$res->end($response->getContent()); $this->app->forgetInstance('request'); $this->app->forgetInstance('datatables.request'); $this->app->forgetInstance(\Dingo\Api\Http\Middleware\Request::class);
Full final:
<?php use Illuminate\Http\Request; use Illuminate\Http\Response; define('LARAVEL_START', microtime(true)); require __DIR__ . '/../vendor/autoload.php'; $app = require_once __DIR__ . '/../bootstrap/app.php'; class Laravel { /** * Illuminate\Foundation\Application * * @var \Illuminate\Foundation\Application */ public $app; /** * App\Http\Kernel * * @var \App\Http\Kernel */ public $kernel; /** * App\Http\Requests\Request * * @var \App\Http\Requests\Request */ public $request; /** * Illuminate\Http\JsonResponse * * @var \Illuminate\Http\JsonResponse */ public $response; /** * structure * * @param \Illuminate\Foundation\Application $app */ public function __construct(\Illuminate\Foundation\Application $app) { $this->app = $app; } /** * RUN * * @return void */ public function run() { \Swoole\Runtime::enableCoroutine(true); $http = new swoole_http_server('127.0.0.1', '80'); $http->set([ 'document_root' => public_path('/'), 'enable_static_handler' => true, ]); $http->on('request', function ($req, $res) { try { $kernel = $this->app->make(Illuminate\Contracts\Http\Kernel::class); $get = $req->get ?? []; $post = $req->post ?? []; $input = array_merge($get, $post); $cookie = $req->cookie ?? []; $files = $req->files ?? []; $server = $req->server ?? []; $request = Request::create($req->server['request_uri'], $req->server['request_method'], $input, $cookie, $files, $server); if (isset($req->header['x-requested-with']) && $req->header['x-requested-with'] == "XMLHttpRequest") { $request->headers->set('X-Requested-With', "XMLHttpRequest", true); } if (isset($req->header['accept']) && $req->header['accept']) { $request->headers->set('Accept', $req->header['accept'], true); } $response = $kernel->handle($request); $res->status($response->getStatusCode()); foreach ($response->headers->allPreserveCaseWithoutCookies() as $name => $values) { foreach ($values as $value) { $res->header($name, $value, false); } } foreach ($response->headers->getCookies() as $cookie) { $res->header('Set-Cookie', $cookie->getName() . strstr($cookie, '='), false); } dump(time()); $res->end($response->getContent()); $this->app->forgetInstance('request'); //$this->app->forgetInstance('session'); //$this->app->forgetInstance('session.store'); //$this->app->forgetInstance('cookie'); $this->app->forgetInstance('datatables.request'); $this->app->forgetInstance(\Dingo\Api\Http\Middleware\Request::class); //$kernel->terminate($request, $response); } catch (\throwable $e) { echo $e->getMessage(); echo PHP_EOL; echo $e->getFile(); echo PHP_EOL; echo $e->getLine(); echo PHP_EOL; } }); $http->start(); } } (new Laravel($app))->run();
test
It's a lot faster than native laravel (there are four SQL queries left).
Note, the code given here can be used for reference, but has not been verified for a long time. And different projects actually use different packages. In the process of debugging, service providers in the debug container and tracking code are needed to tune.
Known problems
- There is a problem in the display of flash data and form validation errors
- PDO will report Cannot execute queries while other unbuffered queries are active symfony/symfony...
- The IP acquisition setting of Throttle will cause problems by default
For more information, please visit: