【建议收藏】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 分支(https://github.com/mabu233/sdebug)
swoft 因为文档不够详细,有时候必须看源码,跟踪运行,断点调试必不可少
composer 扩展
swoft/devtool(用于数据库迁移,实体生成)ctfang/swoft-admin(devtool 无界面过度库,开发界面操作,日记查看、在线代码查看、路由生成、控制器生成等等)
Swoft 安装无特别,跳过
composer create-project swoft/swoft swoft
二、配置修改,常用环境.env 配置新增
HTTP_PORT http服务端口DB_DSN数据库 dnsDB_USERNAME数据库用户名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 本身字符串是省去的。
数据大时候,节省的内存非常可观,对比数组赋值,几十倍都有可能。
【建议收藏】swoft的最佳实践的更多相关文章
- 【Web前端开发最佳实践系列】前端代码推荐和建议
一.常用的前端文件的组织结构: 1.js (放置JavaScript代码) lib(放置框架JavaScript文件) custom.js 2.css(放置CSS样式代码) lib(放置框架CSS文件 ...
- MaxCompute 构建企业云数据仓库CDW的最佳实践建议
在本文中阿里云资深产品专家云郎分享了基于阿里云 MaxCompute 构建企业云数据仓库CDW的最佳实践建议. 本文内容根据演讲视频以及PPT整理而成. 大家下午好,我是云郎,之前在甲骨文做企业架构师 ...
- 给JavaScript初学者的24条最佳实践
.fluid-width-video-wrapper { width: 100%; position: relative; padding: 0 } .fluid-width-video-wrapp ...
- mongodb 最佳实践
MongoDB功能预览:http://pan.baidu.com/s/1k2UfW MongoDB在赶集网的应用:http://pan.baidu.com/s/1bngxgLp MongoDB在京东的 ...
- web移动开发最佳实践之html篇
一.前言 在目前的移动应用开发大潮下,使用web技术进行移动应用开发正变得越来越流行,它主要使用html5.css3.js等技术,在跨平台性.可移植性方面具有无可比拟的优势,特别适合开发对性能要求不太 ...
- Unite Shanghai 2019全日程曝光(建议收藏)
https://mp.weixin.qq.com/s/KvAyXpDhqWROtTX1Ol3a4Q 5月10-12日,Unite Shanghai 2019即将在上海国际会议中心正式开幕.本次大会共设 ...
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- 解密国内BAT等大厂前端技术体系-腾讯篇(长文建议收藏)
1 引言 为了了解当前前端的发展趋势,让我们从国内各大互联网大厂开始,了解他们的最新动态和未来规划.这是解密大厂前端技术体系的第三篇,前两篇已经讲述了阿里和百度在前端技术这几年的技术发展.这一篇从腾讯 ...
- MaxCompute表设计最佳实践
MaxCompute表设计最佳实践 产生大量小文件的操作 MaxCompute表的小文件会影响存储和计算性能,因此我们先介绍下什么样的操作会产生大量小文件,从 而在做表设计的时候考虑避开此类操作. 使 ...
随机推荐
- 利用CloudFlare自动DDNS
注意要 仅限 DNS 获取咱的Key https://dash.cloudflare.com/profile 先在控制面板找到咱的目前IP,然后到Cloudflare中新建一个A记录,如:ddns.y ...
- Fisher算法+两类问题
文章目录 一.Fisher算法 二.蠓的分类问题: 三.代码实现: 一.Fisher算法 二.蠓的分类问题: 两种蠓Af和Apf已由生物学家根据它们的触角和翼长加以区分(Af是能传播花粉的益虫,Apf ...
- Python基础点记录1
1 变量:一个变量就是一个单词,只有一个单一的值 1 Python里面的数据类型 interage , floats , booleans , String等 2 Python是一个区分大小写的语言 ...
- 字符串学习总结(Hash & Manacher & KMP)
前言 终于开始学习新的东西了,总结一下字符串的一些知识. NO.1 字符串哈希(Hash) 定义 即将一个字符串转化成一个整数,并保证字符串不同,得到的哈希值不同,这样就可以用来判断一个该字串是否重复 ...
- SpringBoot多数据库连接(mysql+oracle)
出于业务需求,有时我们需要在spring boot web应用程序中配置多个数据源并连接到多个数据库. 使用过Spring Boot框架的小伙伴们,想必都发现了Spring Boot对JPA提供了非常 ...
- springboot(八)内置SpringMvc静态文件地址修改
参考:作者:恒宇少年链接:https://www.jianshu.com/p/c6ab1081fd5f 介绍: SpringMVC大家都不陌生,而被SpringBoot集成的SpringMVC除了 ...
- Java MD5获取
MD5算法具有以下特点: 1.压缩性:任意长度的数据,算出的MD5值长度都是固定的. 2.容易计算:从原数据计算出MD5值很容易. 3.抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD ...
- 第九章 Lambda&方法引用
9.1.Lambda表达式 9.1.1.标准格式 (形式参数) -> {代码块} 9.1.2.使用前提 有一个接口并且接口中有且仅有一个抽象方法 9.1.3.常见应用 9.1.3.1.无参无返回 ...
- Python while 循环中使用 else 语句
Python while 循环中使用 else 语句: else:表示 while 中的语句正常执行完,然后执行 else 语句的部分. 示例: # while 判断条件: # 一行语句 或 多行语句 ...
- 下载excel模板,导入数据时需要用到
页面代码: <form id="form1" enctype="multipart/form-data"> <div style=" ...