当前位置: 首页 > news >正文

Laravel / Lumen 实践总结

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

不要造轮子

业务推进不应该耗在轮子制造上

  • 典型、常见的功能首先考虑Laravel框架是否已有实现,其次搜索开源的轮子
  • Composer兴起:PHP进入现代化开发阶段、大家可以共享优秀的轮子
  • 使用现成的轮子
    • 框架内置的轮子:适度定制满足业务,以后框架升级最为方便
    • 大牛开源的轮子:功能丰富、架构规范、拓展性强、文档完善、持续维护!!

现成轮子不满足部分需求或有Bug?

  • 不要直接修改!!vendor目录下框架内部组件第三方包
    • 造成包无法进行后续更新
    • Compser重装vendor包后,定制修改将会丢失
  • 新建逻辑分层进行定制(比如Libraries目录)
    1. 目录结构组织参照vendor下的原始实现类
    2. extends原始实现类覆盖需要定制的方法,或者直接implements其整个Constract约定
    3. 在业务逻辑中(而不是vendor目录)替换为自定义类

几个轮子参考站点

  • Laravel专属包搜索:http://packalyst.com
  • Composer官方搜索:https://packagist.org
  • Github搜索:https://github.com
  • Laravel一些开源项目:http://openlaravel.com
  • Spatie开源的Laravel项目:https://spatie.be/en/opensource/laravel
  • PHP优秀包联盟:http://thephpleague.com

Laravel主流分层思想

系统架构需要逻辑分层,每个分层遵循单一职责原则 主流分层

Web分层

  • Controller层作为业务逻辑的总调度,可注入ServiceRepository
  • Service层辅助Controller层,抽象复杂业务逻辑、抽象公共服务、处理第三方功能调用等
  • Repository层具体处理CURDSQL业务、第三方数据调用等资源操作逻辑,可注入Model
    • 需要面向接口开发, 依照接口声明处理 DB、Cache、Api等实现
  • Model层作为业务实体,处理常量定义关联关系配置定义
  • View层处理视图展现

Api分层

1. 业务:Dingo路由 + Controller调度 + Service业务逻辑 -> Transformer数据修饰输出

2. 数据逻辑:Query过滤参数&Repository查询 + Hydrator数据校验并存储 -> Policy鉴权策略

3. 数据:Model(域、常量、关联) + Migration、Factory、Seeder

4. 配置:Config配置 > ENV环境变量

*. 其它:Test(状态码、数据结构、过滤条件)

Laraval权限分层

1. 顶层基于Auth中间件的用户身份认证
2. 主体**基于角色**的RBAC权限架构设计
  - 基于角色分类组织权限节点
  - 决定某个角色能使用什么功能、能做什么操作
3. 底层**基于用户**的鉴权
  * 基于Gate的资源无关操作鉴权
    - 鉴权用户能否某种操作,一般与资源实例无关
    - 定义了单一权限节点的鉴权逻辑
  * 基于Policy的Model实例资源鉴权
    - 鉴权用户能否对Model实例资源进行某种操作
    - 封装资源的多个权限节点鉴权逻辑于一个策略中,并与Model绑定

错误和异常处理

使用异常的好处

  • 不用针对正常、错误的返回而使用类似[status=>sucees, data => $data]这种结构
  • 业务中引入异常体系后,逻辑更加语义化

异常处理原则

  • 业务设计之内的异常,自己抛出自己捕获处理
    • 正常场景就返回数据, 错误场景就抛出异常
    • 抛出的异常在外层业务进行捕获并进一步处理
  • 业务设计以外的异常, 自己未能捕获,冒泡至Handler顶层异常处理器处理
  • 异常基类
    • 需要显示的异常继承自\Symfony\Component\HttpKernel\Exception\HttpException
    • 业务逻辑中组织的异常继承自\Exception、\RuntimeException等 错误和异常

错误日志系统

  • 典型的报错日志系统(有缺陷
    • 日志源抓取 Laravel StorageLogPHP error.logNginx error.log
    • 只提供错误点的调用栈信息
    • 缺少当时场景的关键信息,调试排错困难
  • 使用Laravel顶层异常处理器衔接报错日志系统推荐
    • PHP7下所有ErrorException都是Throwalbe接口的实现,均可被Catch
    • report()方法中进行异常上报可实现当时场景关键上下文信息串联,提高排查效率
      • 当时的用户对象
      • 当时完整的用户请求数据
      • 当时的异常堆栈信息

依赖注入

自动依赖注入 常用于容器自动注入空Model实体对象业务逻辑模块

  • 构造函数注入public function __construct(User $user)
  • 接口注入
    • 控制器方法中:public function index(Request $request)
    • 队列Jobhandle()方法中:public function handle(MailService $mailService)
    • 等等

手工依赖注入 常用于手工注入具化Model实体对象同接口下 不同的业务模块实现

  • Set注入public function setUser(User $user);

使用场景区别举例
Repository层的工作依赖于Model实体,不同场景下使用不同的注入方式

  • 查询场景下 - 自动依赖注入
    • 通过构造函数来注入空Model实体
    • 通过空Model实体发起newQuery进行查询
  • 更新场景下 - 手工依赖注入
  • 通过Setter来注入具化Model实体idRepository
  • 注入的具化Model实体将作为数据更新目标

集成测试

  • 即便做不到TDD,至少粗粒度上的集成测试来保证接口可用性,避免人工测试的困难
  • 核心逻辑模块可以考虑更细粒度的单元测试
1. 指定测试方法 `phpunit --filter clsTest::testMethod`
2. 测试临时忽略指定检查,添加注解 @SupressWarnings("规则名")  
3. 测试覆盖范围
    - 常规场景数据返回: 数据 & 结构 & 状态码
    - 异常场景数据返回:数据不存在
    - 所有过滤字段
    - 分页功能:指定分页 & 单页条数
    - 数据录入 & 更新 正常

遇过的坑

  • 连不上mysql容器实例,找不到host,无法完成migrate迁移操作
    需要在宿主机下做哥容器hostname的host解析

  • factory数据异常 考虑重启docker容器

  • factory中faker一个datetime数据时, 留意给出format格式

  • 进入tinker交互式环境后代码更新没有及时展现出来
    tinker将以进入环境时内存中的代码逻辑来运转,后期代码的更新不会在tinker环境中生效

  • 删除某个文件后, 程序运行报错类不存在
    删除composer缓存文件,composer dumpautoload --optimize

  • 集成测试时的测试数据准备
    需要留意, 除了主体测试数据需要准备外,还需要准备关联数据

  • 报错调试
    查看报错信息一定从框架自带日志着手, 因为报错细节已被框架截获转发到自带日志上, php日志及程序返回中已抹除报错细节

  • Transformer里留意数字类型字段输出的强制类型转换

  • 如果migration操作涉及到SQLite驱动,则务必将每个字段调整封装进单独一个Schema闭包中,否则将出现各种异常

  • 宿主机测试通过,容器内不通过, 错误提示信息是类不存在。

    • 检查命名空间
    • 检查文件名路径

PHPStorm

  • 安装Laravel Plugin,并在项目中启用(每个项目都得单独启用)
  • Settings->Directories中标示app为Sources目录, 指定其Package Prefix为App
  • Alt+Insert快捷键 自动生成代码
  • Alt+Enter快捷键 智能补全注释
  • Ctl+MouseOver快捷键 函数提示

转载于:https://my.oschina.net/u/2400083/blog/830898

相关文章:

  • 对象存储、快存储、文件存储的区别
  • 恶意程序入侵 dbuspm-session 发现了新的方法制这种恶意程序
  • 图示 Smart-Art
  • js中的正则表达式入门
  • Maven中的SNAPSHOT版本和正式版本理解
  • rabbitMq ubuntu下安装
  • 搜索框自动联想功能
  • JavaWeb应用出现HTTP 500-Unable to compile class for JSP 错误 的解决
  • Go 语言入门一: Go 安装
  • Go 获取当前可执行文件的所在目录
  • 认识clientWidth/offsetWidth/scrollWidth
  • angularjs ng-grid 表格使用
  • shllter自动和手动实例
  • easyui datagrid 列的内容超出所定义的列宽时,自动换行
  • 性能优化之快速响应的用户界面
  • ➹使用webpack配置多页面应用(MPA)
  • Fabric架构演变之路
  • hadoop集群管理系统搭建规划说明
  • mongodb--安装和初步使用教程
  • MySQL主从复制读写分离及奇怪的问题
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • SQLServer插入数据
  • 包装类对象
  • 前端相关框架总和
  • 前言-如何学习区块链
  • 巧用 TypeScript (一)
  • 软件开发学习的5大技巧,你知道吗?
  • nb
  • postgresql行列转换函数
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (33)STM32——485实验笔记
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (二)pulsar安装在独立的docker中,python测试
  • (二)学习JVM —— 垃圾回收机制
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (力扣)循环队列的实现与详解(C语言)
  • (十六)串口UART
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)基于IDEA的JAVA基础10
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)EOS中账户、钱包和密钥的关系
  • .dwp和.webpart的区别
  • .Net IE10 _doPostBack 未定义
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • .sys文件乱码_python vscode输出乱码
  • :中兴通讯为何成功
  • [ACL2022] Text Smoothing: 一种在文本分类任务上的数据增强方法