Light-PHP 基於 swoole 的高效能 PHP 框架

woann發表於2018-12-20

?Light-php是一個基於swoole的高效能php框架,輕量的封裝和易用性,使它在中小型高效能專案中有著出色的表現。專案地址: https://github.com/woann/Light-php

環境要求

依賴 說明
PHP >= 7.2 推薦7.2
Swoole >= 4.2.9 從2.0.12開始不再支援PHP5 推薦4.2.9+
Linux 大部分的linux系統都可以 推薦centos

安裝教程

1-1.透過Composer安裝(packagist),此方式安裝版本可能不是最新的,出現此問題請用1-2方式安裝。

composer create-project woann/light-php -vvv

1-2.透過Git安裝。

git clone https://github.com/woann/Light-php.git

2.重新命名.env.example檔案為.env,並配置

3.專案根目錄下執行 php bin\light start 啟動服務

image.png

4.瀏覽器訪問http://127.0.0.1:9521 即可看到歡迎頁面。至此,框架就安裝完成了。

配置檔案

1.Light-php的配置檔案在/config目錄下,框架整合了全域性環境配置檔案/.env,常規配置都在.env檔案中進行配置。

2./config/app.php,框架主要配置檔案主要用來配置swoole擴充套件相關引數。

3./config/databases.php,資料庫配置檔案,配置了資料庫連線相關引數。

4./config/hook.php,配置鉤子(鉤子主要用來將業務邏輯和通知服務分離)。

5./config/redis.php,redis配置檔案,配置了redis連線相關引數。

6./config/route.php,路由配置檔案。

7.以上配置檔案具體引數意義在程式碼中都有註釋,這裡不做更多介紹

路由

以下是一個路由示例/config/route.php,包含http路由和websocket路由(注意:路由中,控制器引數為控制器的簡寫,實際控制器檔案應在後追加Controller)

return [
    'm'             => 'index',    //預設模組
    'c'             => 'index',    //預設控制器
    'a'             => 'init',     //預設操作
    'ext'           => '.html',    //偽靜態字尾    例如 .html
    'http'          =>  [          //http路由
        //uri-----請求方法----模組/控制器/方法----[中介軟體]
        '/'     => ['GET','Index/Index/index','Test'],
        'test/'    => ['GET','Index/Index/ws']
    ],
    'websocket'     =>  [           //websocket路由
        //uri----模組/控制器/方法
        'ws' => 'Index/WebSocket/index',
    ]
];

中介軟體

中介軟體檔案應建立在/app/Middleware目錄下,類名與檔名要一致,並實現Lib\Middleware介面,中介軟體處理方法名必須為handle,過濾後如果透過最終返回結果必須為true。示例:

<?php
namespace app\Middleware;

use Lib\Middleware;
class Test implements Middleware{
    public function handle($request)
    {
        //在此處理中介軟體判斷邏輯,
        //...

        //程式最後透過驗證後,返回true;
        return true;
    }
}

控制器

1.建立控制器,控制器檔案應建立在/app/Controller目錄下,類名與檔名要一致,必須繼承Lib\Controller類,示例:

<?php
namespace app\Controllers\Index;

use Lib\Controller;

class IndexController extends Controller {
    //普通輸出
    public function index()
    {
        return 'hello world';
    }

    //輸出json
    public function index1()
    {
        return $this->json(["code" => 200, "msg" => "success"]);
    }

    //呼叫模板
     public function index2()
    {
        $a = "test";
        //輸出/app/resources/views目錄下index.blade.php模板,並攜帶引數$a。支援用 . 拼接模板路徑(和laravel中模板引擎部分一樣)
        return $this->view("index",["a" => $a]);
        //也可以直接呼叫view函式
        return view("admin.index",["a" => $a]);
    }

}

2.獲取引數

    //獲取get引數
    $this->request->get();//獲取所有get引數:array
    $this->request->get("name");//傳參字串,獲取key為name的引數:string
    $this->request->get(["name","age"]);//傳引數組,獲取key為name和age的引數:array

    //獲取post引數
    $this->request->post();//獲取所有get引數:array
    $this->request->post("name");//傳參字串,獲取key為name的引數:string
    $this->request->post(["name","age"]);//傳引數組,獲取key為name和age的引數:array

    //獲取上傳檔案
    $this->request->getFiles();//獲取所有
    $this->request->getFile("image");//獲取指定檔案
    //檔案上傳
    //--------檔案----[路徑](基於/resources/uploads/)---[新檔名](預設為隨機生成)
    uploadFile($file,"banner","test.png");//上傳檔案方法 開發者也可以不用此方法自己寫上傳操作

鉤子

1.建立鉤子,鉤子檔案應建立在/app/Hook目錄下,類名與檔名要一致,必須繼承Lib\BaseHook類,示例:

<?php
namespace app\Hook;

use Lib\BaseHook;
use Lib\Log;
class TestHook extends BaseHook {
    public function start($name,$ip,$port)
    {
        //當server啟動時執行此鉤子
        Log::getInstance()->write('INFO',$name,"啟動成功","{$ip}:{$port}","at",date('Y-m-d H:i:s'));
    }
    public function open($server,$fd){
        //可以在此執行websocket連結成功後繫結使用者id和fd的操作
    }
    public function close($server,$fd){
        //可以在此執行websocket關閉連結後解綁使用者id和fd的操作
    }
}

2.在鉤子配置檔案/app/config/hook.php中註冊鉤子

<?php
return [
    //Server::onStart
    'start'     => [
        [\app\Hook\TestHook::class,'start'],
    ],
    //Server::onOpen
    'open'      => [
        [\app\Hook\TestHook::class,'open'],
    ],
    //Server::onClose
    'close'     => [
        [\app\Hook\TestHook::class,'close'],
    ],
];

3.使用鉤子

//--獲取鉤子服務例項----監聽方法--鉤子名---引數(...)------
Hook::getInstance()->listen("start",$this->name,$this->config['ip'],$this->config['port']);

Task任務

1.建立Task類,Task檔案應建立在/app/Task目錄下,類名與檔名要一致,示例:

<?php
namespace app\Task;

class Notice{
    /**
     * 給所有線上客戶端傳送訊息
     * @param $fd       發起請求的FD
     * @param $data     要傳送的內容
     *
     * @return bool
     */
    public function ToAll($fd,$data){
        $fds = [] ;//用來存放所有客戶端fd
        foreach($this->server->connections as $client_fd){
            if($fd != $client_fd && $this->server->exist($client_fd)){
                //迴圈向客戶端輸出訊息,排除掉髮送者fd
                $this->server->push($client_fd,$data);
                $fds[] = $client_fd;
            }
        }
        return "已向[".join(",",$fds)."]傳送通知內容:".$data;
    }
}

2.控制器中投遞任務

//---------獲取task示例----賦值server---------------投遞任務---任務類------------方法------------引數
\Lib\Task::getInstance()->setServer($this->server)->delivery(\app\Task\Notice::class,'ToAll',[1,"123"]);

WebSocket

1.開啟websocket server,配置.env檔案SERVER_TYPE=websocket,此配置環境下可同時監聽http

2.定義路由,參考文件路由部分,在路由配置檔案/config/route.phpwebsocket索引下定義路由。

3.控制器示例

<?php
namespace app\Controllers\Index;

use Lib\WsController;
class WebSocketController extends WsController {
    public function index()
    {
        //給客戶端傳送訊息
        //$this->>fd 客戶端唯一標示
        //$this->>server websocket server物件(此物件提供的功能參考swoole文件)
        //
        $data = "哈哈哈我是一條訊息";
        $data2 = "這是一條透過task任務群發訊息";
        $this->server->push($this->fd,$data);
        //投遞非同步任務
        $this->task->delivery (\app\Task\Notice::class,'ToAll',[$this->fd,$data2]);
    }

}

4.前端略過(檢視目錄中有一個ws.blade.php檔案,可以用來測試websocket)...

資料庫

資料庫採用laravel框架的Illuminate\Database,熟悉laravel的小夥伴可極速上手。

1.查詢構建器,參考文件

<?php
namespace app\Controllers\Index;

use Lib\Controller;
use Lib\DB;
class IndexController extends Controller {

    public function index()
    {
        $res = DB::table('user')->where('id',1)->first();
    }

}

2.Model,參考文件

namespace app\Models;

use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    protected $table = 'user';
}

壓力測試

  • 呼叫框架內一個json輸出方法,輸出如下內容:

    {
    "word": "hello world"
    }

    image.png

  • 方法內有一條查詢語句的壓力測試

    public function index(){
        $res = DB::table('user')->where('id',"=","1")->first();
        return $this->json($res);
    }

    image.png

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章