2015年毕业至今,第一份工作即将结束,总结一下自己写出的bug,权当自省,待以后当作checklist使用。
bug环境:Yii2 Advanced框架,Mysql数据库
1. 列表共性问题
(1)排序规则:按某个字段常规升降序不能满足需求
方案:使用mysql的order by field(column,v1,v2,v3)解决
(2)搜索规则:搜索字段,匹配规则(模糊或精确)
(3)搜索状态保留问题:从列表页进到其他页面操作在跳回到列表页时搜索状态应保留
方案:
1)页面跳转时将列表页状态信息通过url传递到目标页面(当时只能想到这样的笨方法)
2)借助H5的sessionStorage在离开页面时存储页面状态信息,能够在一次会话内保留,不同窗口间不共享(不同于localStorge)
(4)搜索内容过滤:前后空格,特殊字符
(5)列表页条目数问题:当展示联表查询结果时,若存在一对多的关系,会出现展示出的条目数与分页条目数不一致的情况
问题原因:Yii的ActiveRecord会对每一页的联表查询结果进行去重处理,所以若联表查询的主表与关联表存在一对多关系时会被过滤掉,只保留第一条,导致某些页面条目数不足整页;
从源码来看:
1)首先GridView小部件会先获取查询结果总条数:yiidataBaseActiveDataProvider::getTotalCount() --> yiidataActiveDataProvider::prepareTotalCount() --> yiidbQuery::count() ,此时查询结果并不会进行去重。
2)yiidbActiveQuery::all() --> yiidbQuery::all() --> yiidbActiveQuery::populate() --> yiidbActiveQuery::removeDuplicatedModels()
removeDuplicatedModels()默认根据主键对查询结果去重,但是这一方法的执行需要满足两个条件:1)存在联表查询;2)未指定indexBy信息。
解决方案:若明确存在一对多关联,且不关心关联表的具体数据,则在查询时使用distinct()方法去重,保障gridView显示的条目数量也为去重后的结果。
(6)列表项内容宽度溢出或内容过少的样式处理
2. 表单共性问题
(1)表单重复提交:提交按钮可重复点击,导致表单重复提交;
方案:定义一个变量记录表单是否已成功提交,提交表单前先判断是否可以提交。
(2)输入格式校验:必填校验,字符长度(中英文),数值(整数,小数,分数,百分数),手机号,邮箱,身份证号,全角字符
(3)客户端校验:时机,提示方式
(4)服务端校验:注意要和客户端校验规则一致
(5)数值类型:
- 范围:上限,下限
- 负值和零
- 浮点数精度:js,php,mysql
- 资金:(1) decimal (2) bigint 按分/厘来存
(6)日期类型需注意
- h5的日期选择控件在录入非法日期时会取到空的value;
- 超过四位数年份会引起数据库datetime字段溢出;
- 日期区间合法性判断
3. 弹出框共性问题
(1)多次打开关闭的状态保留问题:通常要求不保留关闭前的状态
(2)bootstrap模态框Modal嵌套弹框存在bug:弹框中嵌套弹框时,点击半透明区域关闭所有弹框后仍有一个半透明遮罩保留。
方案:关键是避免点击半透明区域关闭弹框,方法是将class为‘modal-dialog’的div的宽和高设为100%,因其背景透明即时将遮罩层盖住,也不会影响视觉,但是半透明区域不会接收到点击事件,不会触发上述bug。
4. 程序错误
(1)程序逻辑问题
(2)sql逻辑问题
(3)异常分支没有跑到导致隐藏bug
(4)功能耦合:难以掌控现有功能修改对其他模块的影响
(5)与产品或测试对需求理解不一致
5. 切记要确认的需求细节
(1)数据细节:数据来源,可用数据过滤条件
(2)交互细节:联动,自动计算,校验时机,校验条件
(3)页面跳转:新窗口,弹出框,当前页面打开,是否允许回退(对于已删除内容应回退到哪里)
(4)边界问题:理想状态不会发生的场景
(5)命名统一:标题,字段,类型/状态
(6)输入内容前后空格处理方式
6. 需注意的样式细节
(1)对齐:元素对齐,边距居中
(2)状态:点击(down,up),获得焦点,失去焦点,鼠标滑过,悬浮,滑出
(3)间距:留白
(4)数据:空数据,有数据,数据过长,换行
7. 错误处理方式
(1)前台操作失误/失败:提示方式与提示内容
(2)后台操作异常/错误:前台的响应方式,后台的异常/错误处理方式
8. 安全
(1)js脚本注入,html代码注入
$html = '<div>div</div><script>alert("htmlxss");</script>'; echo $html;//会弹框 echo htmlentities($html);//输出div元素和其它字符 echo '<br>'; echo htmlspecialchars($html);//原样输出所有字符 echo '<br>'; echo addslashes($html);//输出div元素,与转义后的脚本(审查元素可见脚本) echo '<br>'; echo urlencode($html);//输出url编码后的字符串 echo '<br>'; $url = 'index.php?r=site/about&id=<script>alert("urlxss");</script>'; echo $url;//会弹框 echo htmlspecialchars($url);//原样输出所有字符 echo '<br>'; echo addslashes($url);//原样输出脚本外的所有字符,审查元素可见转义后的脚本 echo '<br>'; echo urlencode($url);//输出url编码后的字符串 echo '<br>';
(2)sql脚本注入
(3)文件上传:文件类型伪装,上传文件大小溢出
/** * 获取文件真实类型 * @param $filename 文件路径 * @param $onlyExt 只返回文件后缀 */ public function getRealType($filename,$onlyExt = true){ $finfo = finfo_open(FILEINFO_MIME_TYPE); $realType = finfo_file($finfo, $filename); finfo_close($finfo); return $onlyExt ? basename($realType) : $realType; }