swoft 假的最佳實踐

selden發表於2019-10-11

這是一篇使用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分支](https://github.com/mabu233/sdebug
swoft因為文件不夠詳細,有時候必須看原始碼,跟蹤執行,斷點除錯必不可少
composer擴充套件 swoft/devtool(用於資料庫遷移,實體生成)、ctfang/swoft-admin(devtool無介面過度庫,開發介面操作,日記檢視、線上程式碼檢視、路由生成、控制器生成等等)

Swoft 安裝無特別,composer即可,跳過

配置修改,常用環境.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()函式是不限制在配置檔案用的,只是一般為了業務擴充套件,習慣在配置使用而已。

重要目錄劃分

  1. 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()])

  1. app/Model/Dao
    專案內部資料庫操作類。例如使用者操作curd就可以定一個UserDao
  2. app/Model/Data
    跨模組資料定義,有一點像資料快取層,但是Data不是用於放跨多起請求有效的快取,例如session for redis就不適用了,但是從redis取出來的session資料後,轉化成SessionData就可以放到Data目錄,因為SessionData物件是當前請求有效的。
  3. app/Model/Service
    外部專案和內部專案的對接層,也可以有小部分業務處理;例如:
    定義一個蘋果支付AppStoreService,那麼它和蘋果支付服務對接的。
    定義一個支付服務 PayService,它是使用者初始化支付庫的配置的(目前推存 yurunsoft/pay-sdk,吐槽下這個庫不是psr編碼規範,強迫症要犯了)
  4. app/Model/Entity
    資料庫實體,由 Devtool 生成,沒有必要手動修改
  5. 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 斷點啟動,
swoft假的最佳實踐

在程式碼新增斷點,在程式碼左側行數旁邊,滑鼠點選,就可以新增

swoft假的最佳實踐

啟動斷點,點選小蟲子圖示

swoft假的最佳實踐

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

Sql除錯

修改 app/Listener/RanListener.php,取消註釋 output()->info($rawSql);,就會把所有sql列印到控制器。
如果線上的測試環境,可以新增 Log::debug($rawSql); ,把sql寫到獨立一個檔案裡,然後使用 ctfang/swoft-admin線上檢視日記。

swoft假的最佳實踐

注意使用 ctfang/swoft-admin,一定設定內網訪問,因為它許可權非常大,可以直接檢視程式碼和執行命令等。

swoft假的最佳實踐

記憶體優化

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

  • 所有資料物件化
  • 例如像匯出excel文件等,最好也是定義一個類檔案進行賦值:

uid username
1 張三

可以定義一個類

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

賦值就可以節省 key 帶來的消耗,物件賦值只是簡單的屬性地址賦值,key本身字串是省去的。
資料大時候,節省的記憶體非常可觀,對比陣列賦值,幾十倍都有可能能。