Laravel 結合 Swoole 簡易版

pwake發表於2020-08-30
<?php
require __DIR__ . '/../vendor/autoload.php';

Swoole\Runtime::enableCoroutine(true,SWOOLE_HOOK_ALL|SWOOLE_HOOK_CURL);//一鍵協程化
$http = new Swoole\Http\Server("0.0.0.0", 3322, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);//建立http伺服器
$http->set([
    'document_root' => __DIR__, // v4.4.0以下版本, 此處必須為絕對路徑
    'enable_static_handler' => true,
    "task_worker_num"=>2,
    "task_enable_coroutine"=>true,
    "task_use_object"=>true
]);

$app = require __DIR__ . '/../bootstrap/app.php';
$app->terminating(function (\Illuminate\Foundation\Application $application) {

    /**
     * 使用 Laravel 的 terminate機制來清除掉髒資料。
     *
     * 由於 AuthManager中的 $guards會儲存每個建立過的 guards 物件,每個 guards 物件又和 user 關聯,如果不清理掉會造成 user資訊混亂
     */
    $auth = $application['auth'];
    $reflect_class = new ReflectionClass($auth);
    $property_guards = $reflect_class->getProperty("guards");
    $property_guards->setAccessible(true);
    if ($property_guards->getValue($auth)){
        $property_guards->setValue($auth, []);
    }

});
$http->app = $app;//將 laravel 的 Application 物件繫結到 swoole的 Server上,這樣就不用透過閉包的方式傳遞 Application物件。

$app->instance("swoole_http", $http);//將swoole的Server物件繫結到 laravel的Application物件上,以便能在業務程式碼中使用,例如 投遞task任務

$http->on("request", function (swoole_http_request $swoole_request, swoole_http_response $swoole_response) use ($http) {

    $app = $http->app;
    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);//建立laravel的 Kernel物件

    Illuminate\Http\Request::enableHttpMethodParameterOverride();
    if (!isset($swoole_request->server["REQUEST_URI"])) {//swoole的 這個請求頭是小寫,cgi 是大寫,相容一下
        $swoole_request->server["REQUEST_URI"] = $swoole_request->server["request_uri"];
    }

    /**
     * 建立 laravel 的 Requests
     */
    $symfony_request = new Symfony\Component\HttpFoundation\Request($swoole_request->get ?: [], $swoole_request->post ?: [], [], $swoole_request->cookie ?: [], $swoole_request->files ?: [], $swoole_request->server ?: []);
    $laravel_request = Illuminate\Http\Request::createFromBase($symfony_request);

    /**
     * 處理請求,獲得 Response 物件,並獲得Response的內容。
     */
    $laravel_response = $kernel->handle($laravel_request);
    $content = $laravel_response->getContent();

    /**
     * 設定響應碼和響應頭
     */
    $swoole_response->status($laravel_response->getStatusCode());
    foreach ($laravel_response->headers->allPreserveCaseWithoutCookies() as $name => $values) {
        foreach ($values as $value) {
            $swoole_response->header($name, $value);
        }
    }

    /**
     * 設定cookie
     */
    foreach ($laravel_response->headers->getCookies() as $cookie) {
        list($cookie_key, $cookie_val) = explode("=", $cookie);
        $swoole_response->cookie($cookie_key, $cookie_val);
    }

    /**
     * 輸出內容
     */
    $swoole_response->end($content);

    $kernel->terminate($laravel_request, $laravel_response);
});
$http->on("task",function ($serv, Swoole\Server\Task $task){});

$http->start();
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章