easyswoole - 基于swoole扩展实现的一款高性能php框架

模板引擎

渲染驅動

EasySwoole 引入模板渲染驅動的形式,把需要渲染的數(shù)據(jù),通過協(xié)程客戶端投遞到自定義的同步進程中進行渲染并返回結果。為何要如此處理,原因在于,市面上的一些模板引擎在 Swoole 協(xié)程下存在變量安全問題。例如以下流程:

  • request A reached, static A assign requestA-data
  • compiled template
  • write compiled template (yield current coroutine)
  • request B reached,static A assign requestB-data
  • render static A data into complied template file

以上流程我們可以發(fā)現(xiàn),A 請求的數(shù)據(jù),被 B 請求給污染了。為了解決該問題,EasySwoole 引入模板渲染驅動模式。

組件要求

  • easyswoole/spl: ^1.0
  • easyswoole/component: ^2.0

安裝方法

composer require easyswoole/template

倉庫地址

easyswoole/template

基礎實現(xiàn)原理講解

實現(xiàn)渲染引擎

<?php
class R implements \EasySwoole\Template\RenderInterface
{
    public function render(string $template, ?array $data = null, ?array $options = null): ?string
    {
        return 'todo some thing';
    }

    public function onException(\Throwable $throwable, $arg): string
    {
        return $throwable->getMessage();
    }
}

舊版本 Template (1.1.0 之前版本) 實現(xiàn)渲染引擎如下:

<?php
class R implements \EasySwoole\Template\RenderInterface
{
    public function render(string $template, ?array $data = [], ?array $options = []):?string
    {
        return 'todo some thing';
    }

    public function afterRender(?string $result, string $template, array $data = [], array $options = [])
    {
        // TODO: Implement afterRender() method.
    }

    public function onException(Throwable $throwable, $arg):string
    {
        return $throwable->getMessage();
    }
}

在自定義 HTTP 服務中調用渲染引擎

<?php
require_once __DIR__ . '/vendor/autoload.php';

class MyRender implements \EasySwoole\Template\RenderInterface
{

    public function render(string $template, ?array $data = null, ?array $options = null): ?string
    {
        return "your template is {$template} and data is " . json_encode($data);
    }

    public function onException(\Throwable $throwable, $arg): string
    {
        return $throwable->getTraceAsString();
    }
}

$renderConfig = \EasySwoole\Template\Render::getInstance()->getConfig();

/*
 * 可選配置
$renderConfig->setTempDir(getcwd()); // 設置 渲染引擎驅動 Socket 存放目錄,默認為 getcwd()
$renderConfig->setTimeout(3); // 設置 超時時間,默認為 3s,不建議修改
$renderConfig->setServerName('EasySwoole'); // 設置 渲染引擎驅動服務名稱,不建議修改
$renderConfig->setWorkerNum(3); // 設置 渲染引擎服務工作進程數(shù),默認為 3,不建議修改
 */

$renderConfig->setRender(new MyRender()); // 設置 渲染引擎

$http = new swoole_http_server("0.0.0.0", 9501);
$http->on("request", function ($request, $response) {
    $ret = \EasySwoole\Template\Render::getInstance()->render('index.html', ['easyswoole' => 'hello']);
    $response->end($ret);
});

// 調用渲染引擎
\EasySwoole\Template\Render::getInstance()->attachServer($http);

$http->start();

舊版本 Template 組件(1.1.0 之前)在自定義 HTTP 服務中調用渲染引擎時,實現(xiàn)渲染引擎接口的方法有些許不同,詳細請看上文實現(xiàn)渲染引擎。

重啟渲染引擎

由于某些模板引擎會緩存模板文件,導致可能出現(xiàn)以下情況:

  • 用戶 A 請求 1.tpl 返回 'a'
  • 開發(fā)者修改了 1.tpl 的數(shù)據(jù),改成了 'b'
  • 用戶 B、C、D 在之后的請求中,可能會出現(xiàn) 'a'、'b'兩種不同的值

那是因為模板引擎已經(jīng)緩存了 A 所在進程的文件,導致后面的請求如果也分配到了 A 的進程,就會獲取到緩存的值

解決方案如下:

  • 1: 重啟 EasySwoole 服務,即可解決
  • 2: 模板渲染引擎實現(xiàn)了重啟方法 restartWorker,直接調用即可
Render::getInstance()->restartWorker();

用戶可以根據(jù)自己的邏輯,自行調用 restartWorker 方法進行重啟。

重啟渲染引擎使用示例

例如:用戶可以在控制器中新增 reload 方法重啟渲染引擎:

1、實現(xiàn)自定義渲染引擎,新建 App\RenderDriver\MyRender.php 文件

<?php

namespace App\RenderDriver;

class MyRender implements \EasySwoole\Template\RenderInterface
{
    public function render(string $template, ?array $data = null, ?array $options = null): ?string
    {
        return "your template is {$template} and data is " . json_encode($data);
    }

    public function onException(\Throwable $throwable, $arg): string
    {
        return $throwable->getTraceAsString();
    }
}

舊版本 Template 組件(1.1.0 之前)實現(xiàn)自定義渲染引擎接口的方法和最新穩(wěn)定版本有些許不同,詳細請看上文。

2、注冊渲染引擎服務

<?php

namespace EasySwoole\EasySwoole;

use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;
use EasySwoole\Template\Render;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');
    }

    public static function mainServerCreate(EventRegister $register)
    {
        $renderConfig = \EasySwoole\Template\Render::getInstance()->getConfig();

        /*
         * 可選配置
        $renderConfig->setTempDir(getcwd()); // 設置 渲染引擎驅動 Socket 存放目錄,默認為 getcwd()
        $renderConfig->setTimeout(3); // 設置 超時時間,默認為 3s,不建議修改
        $renderConfig->setServerName('EasySwoole'); // 設置 渲染引擎驅動服務名稱,不建議修改
        $renderConfig->setWorkerNum(3); // 設置 渲染引擎服務工作進程數(shù),默認為 3,不建議修改
         */

        $renderConfig->setRender(new \App\RenderDriver\MyRender());
        Render::getInstance()->attachServer(ServerManager::getInstance()->getSwooleServer());
    }
}

3、在控制器中新增 reload 方法重啟渲染引擎

<?php

namespace App\HttpController;

use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\Template\Render;

class Index extends Controller
{
    public function index()
    {
        $this->response()->write(Render::getInstance()->render('index.tpl', [
            'user' => 'easyswoole',
            'time' => time()
        ]));
    }

    public function reload()
    {
        Render::getInstance()->restartWorker();
        $this->response()->write('restart worker success!');
    }
}

運行結果:訪問 http://127.0.0.1:9501/ (示例請求地址) 即可看到運行結果: your template is index.tpl and data is {"user":"easyswoole","time":1613659221},然后訪問 http://127.0.0.1:9501/reload (示例請求地址) 即可重啟渲染引擎,看到運行結果 restart worker success!

使用示例(在 EasySwoole 中使用)

使用 Smarty 渲染

引入Smarty

composer require smarty/smarty

實現(xiàn)渲染引擎

新建 \App\RenderDriver\Smarty.php,內容如下:

<?php

namespace App\RenderDriver;

use EasySwoole\Template\RenderInterface;

class Smarty implements RenderInterface
{
    private $smarty;

    function __construct()
    {
        $temp = sys_get_temp_dir();
        $this->smarty = new \Smarty();
        $this->smarty->setTemplateDir(EASYSWOOLE_ROOT . '/App/View/');
        $this->smarty->setCacheDir("{$temp}/smarty/cache/");
        $this->smarty->setCompileDir("{$temp}/smarty/compile/");
    }

    public function render(string $template, ?array $data = null, ?array $options = null): ?string
    {
        foreach ($data as $key => $item) {
            $this->smarty->assign($key, $item);
        }
        return $this->smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false,
            $merge_tpl_vars = true, $no_output_filter = false);
    }

    public function onException(\Throwable $throwable, $arg): string
    {
        $msg = "{$throwable->getMessage()} at file:{$throwable->getFile()} line:{$throwable->getLine()}";
        trigger_error($msg);
        return $msg;
    }
}

舊版本 Template 組件(1.1.0 之前)實現(xiàn)渲染引擎接口的方法和最新穩(wěn)定版本有些許不同,詳細請看上文。Template 1.1.0 之前版本實現(xiàn)如下:

<?php
namespace App\RenderDriver;

use EasySwoole\Template\RenderInterface;

class Smarty implements RenderInterface
{
    private $smarty;

    function __construct()
    {
        $temp = sys_get_temp_dir();
        $this->smarty = new \Smarty();
        $this->smarty->setTemplateDir(EASYSWOOLE_ROOT . '/App/View/');
        $this->smarty->setCacheDir("{$temp}/smarty/cache/");
        $this->smarty->setCompileDir("{$temp}/smarty/compile/");
    }

    public function render(string $template, ?array $data = [], ?array $options = []): ?string
    {
        foreach ($data as $key => $item) {
            $this->smarty->assign($key, $item);
        }
        return $this->smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false,
            $merge_tpl_vars = true, $no_output_filter = false);
    }

    public function afterRender(?string $result, string $template, array $data = [], array $options = [])
    {

    }

    public function onException(\Throwable $throwable, $arg): string
    {
        $msg = "{$throwable->getMessage()} at file:{$throwable->getFile()} line:{$throwable->getLine()}";
        trigger_error($msg);
        return $msg;
    }
}

在 EasySwoole 的 HTTP 服務中調用

首先在 EasySwoole 全局事件 EasySwooleEvent.phpmainServerCreate 事件中注冊渲染引擎服務,注冊示例代碼如下:

<?php

namespace EasySwoole\EasySwoole;

use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');
    }

    public static function mainServerCreate(EventRegister $register)
    {
        // 獲取 Render 配置
        $renderConfig = \EasySwoole\Template\Render::getInstance()->getConfig();

        // [可選配置]
        /*
        $renderConfig->setTimeout(3); // 設置 超時時間,默認為 3s,不建議修改
        $renderConfig->setServerName('EasySwoole'); // 設置 渲染引擎驅動服務名稱,不建議修改
        $renderConfig->setWorkerNum(3); // 設置 渲染引擎服務工作進程數(shù),默認為 3,不建議修改
         */

        // 設置 渲染引擎模板驅動
        $renderConfig->setRender(new \App\RenderDriver\Smarty());

        // 設置 渲染引擎進程 Socket 存放目錄,默認為 getcwd()
        $renderConfig->setTempDir(EASYSWOOLE_TEMP_DIR);

        // 注冊進程到 EasySwoole 主服務
        \EasySwoole\Template\Render::getInstance()->attachServer(\EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer());
    }
}

在控制器層響應(使用示例代碼如下):

首先新建 App\View\custom.html,內容如下:

{$name}

在控制器中進行調用:

<?php

namespace App\HttpController;

use EasySwoole\Http\AbstractInterface\Controller;

class Index extends Controller
{
    public function index()
    {
        $this->response()->write(\EasySwoole\Template\Render::getInstance()->render('custom.html', ['name' => 'Welcome To Use EasySwoole ^_^!']));
    }
}

運行結果:啟動服務,訪問 http://127.0.0.1:9501,即可看到運行結果:Welcome To Use EasySwoole ^_^!

支持常用的模板引擎

下面列舉一些常用的模板引擎包方便引入使用:

smarty/smarty

Smarty 是一個使用 PHP 寫出來的模板引擎,是目前業(yè)界最著名的 PHP 模板引擎之一。

引入方法

composer require smarty/smarty=~3.1

league/plates

使用原生 PHP 語法的非編譯型模板引擎,更低的學習成本和更高的自由度。

引入方法

composer require league/plates=3.*

duncan3dc/blade

Laravel 框架使用的模板引擎

引入方法

composer require duncan3dc/blade=^4.5

topthink/think-template

ThinkPHP 框架使用的模板引擎

引入方法

composer require topthink/think-template

如果用戶想要在 EasySwoole 框架中使用以上模板引擎,具體使用示例可以查看Template 使用示例 或者 Template 組件單元測試用例。上文中講述了使用 Smarty 模板引擎的使用示例,其他模板引擎的使用方法大致類似。

常見問題

注冊渲染引擎失敗,出現(xiàn) UnixSocket bind 失敗

  • 報錯結果類似如下:
PHP Fatal error:  Uncaught EasySwoole\Component\Process\Exception: EasySwoole\Template\RenderWorker bind /work/EasySwoole.Render.Worker.0.sock fail case Operation not permitted in /work/vendor/easyswoole/component/src/Process/Socket/AbstractUnixProcess.php:32
  • 失敗原因:部分 vargrant 服務器或 Docker 服務器沒有權限創(chuàng)建 UnixSocket,導致注冊渲染引擎失敗。
  • 解決方案:注冊渲染引擎時,設置渲染引擎驅動進程 Socket 存放目錄為 '/Tmp'。示例代碼如下:
<?php

namespace EasySwoole\EasySwoole;

use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');
    }

    public static function mainServerCreate(EventRegister $register)
    {
        // 獲取 Render 配置
        $renderConfig = \EasySwoole\Template\Render::getInstance()->getConfig();
        // 設置 渲染引擎模板驅動
        $renderConfig->setRender(new \App\RenderDriver\Smarty());

        ###  設置 渲染引擎進程 Socket 存放目錄為 '/Tmp'  ###
        $renderConfig->setTempDir('/Tmp');

        // 注冊進程到 EasySwoole 主服務
        \EasySwoole\Template\Render::getInstance()->attachServer(\EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer());
    }
}
主站蜘蛛池模板: 河北省建筑科学研究院有限公司| 立式/卧式/暖气/管道泵,管道离心泵选型,管道增压泵型号 - 安平鼎千泵业制造厂 | 石墨热场|PECVD石墨舟|碳碳框|燃料电池双极板|半导体石墨|光纤用石墨模具|石墨电极加工|石墨制品|上海弘竣新能源材料有限公司 | 苏州交通设施_道路划线_停车场划线_厂区划线_环氧地坪厂家-推荐【飞扬市政交通设施公司】专注交通设施8年! | 塑木地板,塑木栏杆,塑木地板价格,塑木地板厂家—浙江尚元塑木制品有限公司 | 液体灌装机-酱料灌装机-全自动灌装机-旋盖机-铝箔封口机-贴标机厂家-迈特威自动化设备(天津)有限公司" | 绍兴宇力半导体有限公司官网| 直流电源|Chroma直流电源|可程控直流电源-卓定电子Chroma代理 | 苏州交通设施_道路划线_停车场划线_厂区划线_环氧地坪厂家-推荐【飞扬市政交通设施公司】专注交通设施8年! | 纳米砂磨机|纳米研磨机|实验室砂磨机-无锡市少宏粉体科技有限公司 | 小地磅,钢瓶秤,叉车称,轮椅秤,倒桶秤,畜牧秤,轴重仪,称重模块——上海实干实业有限公司-网站首页 | 室内去除甲醛检测治理十大品牌_去除甲醛公司加盟-优吸环保科技有限公司集团总部官网 | 西克制冷官网│制冷机组冷风机冷库设备厂家-西克制冷(无锡)有限公司_西克制冷(无锡)有限公司 | 聚丙烯酰胺,聚合氯化铝,重金属捕捉剂,污泥调理剂,活性氧化铝,生石灰,反渗透阻垢剂,工业葡萄糖,硫酸铝,果壳活性炭,柱状活性炭,蜂窝活性炭,石英砂,锰砂-北京雁归来环保科技有限公司-以真诚为立足之本,以质量为生存之本,愿与海内外同仁共创双赢。雁归来人一路走来,气贯长虹,勇锐盖过怯弱,进取压倒苟安!我们紧扣时代脉搏,专注水处理、继往开来! | 物流系统?货代系统?国际快递/专线/小包系统首选?哲盟软件 | 深圳市佳顺优印印刷有限公司,佳顺优印,画册印刷,海报印刷,封套印刷,手提袋印刷,包装盒印刷,彩盒印刷,无碳纸印刷,不干胶印刷,信封印刷,便笺印刷,笔记本印刷,台历印刷,挂历印刷,国际会展中心附近印刷厂,宝安印刷厂,宝安教材印刷厂 | 盘扣租赁|盘扣架租赁|盘扣脚手架|盘扣脚手架租赁|盘扣式脚手架|盘扣式脚手架租赁-北京亚欧盟盘扣租赁有限公司 | 望崖阁书法培训班-杭州书法高考培训班2023届招生简章-优清画院 | 全开式真空干燥机_全开耙式真空干燥机_全开式动态真空干燥机,江阴千峰机械制造有限公司 | 液压万能试验机-液压式万能试验机-万能试验机厂家-济南鸿君试验机 | 陕西散花照明-西安太阳能路灯,陕西太阳能路灯,西安太阳能路灯厂家,陕西太阳能路灯厂家 | 锦州龙威机械有限公司官网 ,锦州医药包装机,包装机,锦州包装机械,小袋颗粒装盒生产线,颗粒装盒生产线,软双铝装盒线,伺服颗粒 | 土壤养分测定仪-土壤养分速测仪-生产厂家-托普云农土壤仪器站 | 葡萄糖酸钠_食用葡萄糖_精萘-安徽鹏腾实业有限公司 | 快达物流:电商和微商的仓储物流外包和托管服务-北京快达国际物流服务有限公司官方网站 | 塑料模具公司,塑料包装桶厂家,PET打包带厂家,缠绕膜厂家-新疆福吉亚工贸有限公司 | 排水PVC管-PVC排污管-给水PVC管-电线PVC管-米阳建材pvc管厂 | 新中式家具,广东新中式家具,广州新中式家具,佛山新中式家具,顺德新中式家具,乐从新中式家具,新中式家具厂家直销--唐明雅居 | 宁波管道安装_宁波工业冷风机_宁波冷风机厂家_宁波厂房通风降温_「浙江甬风机电」 | 行域招聘网-行业领域专业技术人才招聘求职平台 | 油压缓冲器-缓冲器-重庆佑旺机械有限公司[官网]西捷克重庆办事处 | 天津安检机-天津安检门-安检设备租赁-安检设备厂家-华创永信 | 远东齿轮泵|高粘度齿轮泵|三螺杆油泵|沥青保温泵|高粘度稠油泵-远东泵业官网 | 伸缩机厂家-现货快递物流伸缩皮带机|装车输送机-乐清市华森自动化设备有限公司 | 铸铁平台-焊接平台-划线平台-三维焊接平台厂家-泊头市溪海冶金机械设备有限公司 | 无人叉车|智能无人叉车|智能AGV叉车|激光叉车AGV厂家_江西丹巴赫机器人股份有限公司 | 金相切割机-金相磨抛机-显微/维氏/布氏/洛氏硬度计-自准直仪-金相显微镜-万能材料试验机-清洁度检测仪-淋雨试验机-上海中研精密仪器制造有限公司 | 南通出国劳务公司-如东海外经济技术合作有限公司-启东,海门,如皋,海安出国劳务 | 小麦硬度指数仪-石灰活性测定仪-智能型砂强度仪-北京同德创业科技有限公司 | 陕西筱润智能科技有限公司 干部人事智能档案柜 智能密集架 智能档案柜 部队选层文件智能柜 智能枪弹柜 财务智能档案柜 边防武警智能密集架 医院智能档案柜 部队选层文件智能柜智能枪弹柜 学校医院文件柜 企事业单位公检法智能文件柜 生产厂家-筱润智能科技有限公司 RFID射频智能密集架 全自动智能选层档案柜 智能密保柜 枪柜部队营房营具床桌椅办公家具 办公用品档案盒设备货架 全自动智能选层柜生产厂家-筱润智能科技有限公司 | 江苏保捷锻压有限公司(中国汽车零部件供应商,锻造,精加工,热处理) |