­

【建議收藏】swoft的最佳實踐

這是一篇使用 swoft 兩個月後的總結文章!,後續會陸續更新的

這是 web-api 開發的總結,如果使用 websocket 等服務的可能不適用,本章節會對一些規範、習慣,或者優化進行一些說明

一、安裝 & 環境

swoole 安裝

swoft 開發的環境最好是 mac(以下截圖都是以 mac 環境下的)

以下安裝代碼是需要開啟 openssl 擴展的,如果不需要可以直接 pecl install swoole 一路回車即可

$ brew info openssl
--------------------
For compilers to find openssl you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl/include」
* * * * *
複製 /usr/local/opt/openssl
$  pecl install swoole
* * * * *
enable openssl support? [no] : yes --with-openssl-dir=/usr/local/opt/openssl

新手必備擴展

sdebug,兼容 swoole 的 xdebug 分支(//github.com/mabu233/sdebug

swoft 因為文檔不夠詳細,有時候必須看源碼,跟蹤運行,斷點調試必不可少

composer 擴展

  1. swoft/devtool(用於數據庫遷移,實體生成)
  2. ctfang/swoft-admin(devtool 無界面過度庫,開發界面操作,日記查看、在線代碼查看、路由生成、控制器生成等等)

Swoft 安裝無特別,跳過

composer create-project swoft/swoft swoft

二、配置修改,常用環境.env 配置新增

  1. HTTP_PORT http 服務端口
  2. DB_DSN 數據庫 dns
  3. DB_USERNAME 數據庫用戶名
  4. DB_PASSWORD 數據庫用戶密碼

.env 文件是不提交到 git 的,所以不會產生衝突,團隊每個人都新增一份,.env 所有鍵值對都應該在.env.example 存在一份默認值和注釋說明。

使用 .env 里的配置,在 app/bean.php 文件下使用 'port' => env("HTTP_PORT",18306),,當然 env() 函數是不限制在配置文件用的,只是一般為了業務擴展,習慣在配置使用而已。

三、重要目錄劃分

app/Common

對項目內部,公用的、公開的。

定義一個接口返回格式類

<?php

namespace App\Common;

class Message
{
    const EROR = 100;

    public static function ok():array
    {
        return ['code' => 0, 'msg' => "ok", 'data' => null];
    }

    public static function success($data = []):array
    {
        return ['code' => 0, 'msg' => 'ok', 'data' => $data];
    }

    public static function code(array $msg)
    {
        return ['code' => $msg[0], 'msg' => $msg[1], 'data' => null];
    }

    public static function error($msg = 'error', $code = self::EROR, $data = [])
    {
        return ['code' => $code, 'msg' => $msg, 'data' => $data];
    }
}

定義一個狀態碼類

<?php

namespace App\Common;

/**
 * 狀態碼定義
 * @package App\Common
 */
class Code
{
    public const Ok = [0, "ok"];
    public const Unknown = [1, "未知錯誤"];
    public const NotUsers = [2, "用戶不存在"];
}

這樣,所有接口都可以使用 Message::code(Code::NotUsers)Message::success(['time'=>time()])

  • app/Model/Dao

項目內部數據庫操作類。例如用戶操作 curd 就可以定一個 UserDao

  • app/Model/Data

跨模塊數據定義,有一點像數據緩存層,但是 Data 不是用於放跨多起請求有效的緩存,例如 session for redis 就不適用了,但是從 redis 取出來的 session 數據後,轉化成 SessionData 就可以放到 Data 目錄,因為 SessionData 對象是當前請求有效的。

  • app/Model/Service

外部項目和內部項目的對接層,也可以有小部分業務處理;例如:
定義一個蘋果支付 AppStoreService,那麼它和蘋果支付服務對接的。
定義一個支付服務 PayService,它是用戶初始化支付庫的配置的(目前推薦 yurunsoft/pay-sdk,吐槽下這個庫不是 psr 編碼規範,強迫症要犯了)

  • app/Model/Entity

數據庫實體,由 Devtool 生成,沒有必要手動修改

  • app/Model/Logic

邏輯層,範圍很廣,上面 Model 不好分層的時候,就放到這裡好了,所有代碼都是有邏輯的……

四、中間件

swoft 不支持路由分組,所以只能判斷路由,錄入定義一個登錄權限檢查,因為少數一兩個接口不用檢查,只能聲明一個全局中間件,再在中間內部判斷如果是公開路由,就跳過

// 對外公開的接口
$path = $request->getUri()->getPath();
if (in_array($path, self::$publicAction)) {
    $response = $handler->handle($request);
    return $response;
}

往請求賦值

像用 uid 等,因為所有接口都可以使用的,就是需要在中間件可以檢查出來,可以直接賦值到請求對象

$request->uid = $token->uid;

如果某個請求使用的值,可以使用 psr 規範的 withAttribute

$request = $request->withAttribute('test','這是值')

如果你是新項目,可以使用 ctfang/swoft-admin 創建控制器,在創建控制器時候選擇啟用的中間件,這樣就不會漏

在這裡插入圖片描述

五、調試

斷點調試

如果有安裝 sdebug 擴展,需要停止 php-fpm 服務,默認端口衝突,不然不能使用。

新增 phpStorm 斷點啟動,

在這裡插入圖片描述

在代碼新增斷點,在代碼左側行數旁邊,鼠標點擊,就可以新增

在這裡插入圖片描述

啟動斷點,點擊小蟲子圖標

在這裡插入圖片描述

請求來到斷點時候,就會自動停止,等待你點擊下一步才可以繼續運行

Sql 調試

修改 app/Listener/RanListener.php,取消注釋 output()->info($rawSql);,就會把所有 sql 打印到控制器。

如果線上的測試環境,可以新增 Log::debug ($rawSql); ,把 sql 寫到獨立一個文件里,然後使用 ctfang/swoft-admin 在線查看日記。

在這裡插入圖片描述

注意使用 ctfang/swoft-admin,一定設置內網訪問,因為它權限非常大,可以直接查看代碼和執行命令等。

在這裡插入圖片描述

六、內存優化

因為常駐內存,所有內存都是敏感的,不像 fpm,請求結束直接回收。常駐內存後,哪怕是臨時對象,也要等緩衝區滿了,php 才收拾垃圾的,能省一點是一點。

  • 所有數據對象化
  • 例如像導出 excel 文檔等,最好也是定義一個類文件進行賦值:
uid username
1 張三

可以定義一個類

class UserExcelData {
  public $uid;
  public $username;
}

賦值就可以節省 key 帶來的消耗,對象賦值只是簡單的屬性地址賦值,key 本身字符串是省去的。

數據大時候,節省的內存非常可觀,對比數組賦值,幾十倍都有可能。


 

 
Tags: