■ 前端部分
HTML标签的class属性值和id属性值均使用中横线风格,示例:
<div id="form-group">
<span class="border-bottom">...</span>
</div>
HTML标签使用自定义属性必须加“data-”前缀,避免和标准属性冲突。
示例:<tr data-uid="9527">……</tr>
URL的文件名使用中横线风格,参数名使用下划线风格,示例:
https://www.domain.com/html-demo.html?out_trade_no=1217752501201407033233368018&goods_tag=WXG
https://www.domain.com/css-demo.css?version=1.0.0
https://www.domain.com/js-demo.js?version=1.0.0
https://www.domain.com/png-demo.png?version=1.0.0
文件名使用“资源-操作”的格式,以尽量体现出其功能,示例:
product-category-list.html:商品分类列表
product-category-view.html:商品分类查看
product-category-add.html:商品分类添加
product-category-edit.html:商品分类编辑
product-category-delete.html:商品分类删除
表单中<input>的name属性值使用下划线风格,示例:
<input name="out_trade_no" type="text" value="1217752501201407033233368018">
<input name="goods_tag" type="text" value="WXG">
按钮必填属性[type="button"][data-action="xxxxx"]并默认禁用,等绑定好点击事件再解除禁用态,示例:
<button type="button" data-action="login" disabled>登录</button>
<button type="button" data-action="search" disabled>搜索</button>
<button type="button" data-action="article-add" disabled>发布</button>
<button type="button" data-action="submit" disabled>提交</button>
说明①:先使用$('[data-action="xxxxx"]').on('click')绑定点击事件,再使用$('[data-action="xxxxx"]').prop('disabled', false)解除禁用态。
说明②:如果点击事件是执行AJAX请求,那么应该在beforeSend回调里禁用按钮防止重复点击,然后在complete回调里解除禁用态。
■ 后端部分
变量名使用小驼峰风格,对于一类特定类型数据建议使用固定的变量名来保存,以达到望文知义的效果,示例:
$ok:true=成功或正常|false=失败或异常
$row:数据库查询结果(单条记录,一维数组)
$rows:数据库查询结果(多条记录,二维数组)
$rowCount:SQL语句影响的行数,int数据类型
$counter:计数器(递增或递减通用),int数据类型
$bytes:字节数,int数据类型
$isXxx:true=是|false=否,如:$isDelete
$canXxx:true=可以|false=不可以,如:$canDelete
$xxxInstance:xxx实例(类对象),Instance应该作为后缀,如:$userInstance,其它的也类似,如:$xxxModel、$xxxConfig、$xxxDispatcher
$id:单个ID号,int数据类型
$ids:多个ID号,array数据类型,如:[1, 2, 3];统一使用“s”后缀表示变量是数组,且是某一类数据的集合,如:$users = [$user0, $user1, $user2]
$response:接收远程请求的响应结果,如file_get_contents()或curl_exec()的返回值,mixed数据类型,可解析响应结果衍生出$responseArr
$json:JSON字符串
$jsonEncode:接收json_encode()函数的返回值,string|false数据类型
$jsonDecode:接收json_decode()函数的返回值,mixed数据类型
$date:接收date()函数的返回值,string数据类型
$time:接收time()函数的返回值,int数据类型
$count:接收count()函数的返回值,int数据类型
$explode:接收explode()函数的返回值,array数据类型
$implode:接收implode()函数的返回值,string数据类型
自定义常量名(不管是普通常量还是类常量)使用全大写下划线风格,如以下内置常量:
PHP_VERSION、E_WARNING、UPLOAD_ERR_INI_SIZE
自定义函数名使用全小写下划线风格,如以下内置函数:
var_dump()、array_key_exists()、str_replace()、preg_match_all()
自定义类名使用大驼峰风格,类方法名使用小驼峰风格(不推荐使用下划线前缀来表明protected/private可见性),如以下内置类:
ReflectionFunctionAbstract::getNumberOfRequiredParameters()
ReflectionEnumBackedCase::getBackingValue()
SplDoublyLinkedList::setIteratorMode() // spl => Standard PHP Library
SimpleXMLElement::registerXPathNamespace() // 这里虽然XML全大写,但仍建议开发者统一使用首字母大写,后面字母均小写的风格
类名正例:XmlService、TcpUdpDeal、JsonUtil、UrlTool // 对于像xml这类由单词首字母构成的特有名词,建议仅第一个字母大写,后面字母均小写
类名反例:XMLService、TCPUDPDeal、JSONUtil、URLTool
自定义类属性名使用小驼峰风格(不推荐使用下划线前缀来表明protected/private可见性),如以下内置类的属性名:
DOMDocument::xmlEncoding
DOMDocument::strictErrorChecking
基础类命名(统一使用Base前缀,不建议使用Common前缀):
BaseModel:基础模型
BaseController:基础控制器
数据库操作相关方法命名示例:
---------- 数据库类方法 ----------
query($sql, $params):用于SELECT类语句,返回查询结果集(二维数组),如果执行SQL失败则返回false
exec($sql, $params):用于INSERT、UPDATE、DELETE类语句,返回影响记录数,如果执行SQL失败则返回false
---------- 模型类方法 ----------
getRowById($id):查询单条记录(一维数组),如果执行SQL失败则返回false
getRowsByIds($ids):查询多条记录(二维数组),如果执行SQL失败则返回false
getCount():查询符合条件记录数,如果执行SQL失败则返回false
getList():查询多条记录(分页专用),必须先查询符合条件记录数,在记录数大于零时才调用本方法,如果执行SQL失败则返回false
insert($data):插入一条记录,插入成功返回true,否则返回false
insertGetId($data):插入一条记录并返回自增主键值(string类型,如果表没有自增主键则返回空字符串),如果插入失败则返回false
updateById($id, $data):根据主键ID号更新记录(单条)数据,返回影响记录数,如果执行SQL失败则返回false
deleteById($id):根据主键ID号删除记录(单条),返回影响记录数,如果执行SQL失败则返回false
incXxxById($id):根据主键ID号自增xxx字段的值,返回影响记录数,如果执行SQL失败则返回false
decXxxById($id):根据主键ID号自减xxx字段的值,返回影响记录数,如果执行SQL失败则返回false
mixed数据类型的使用:
除非形参或返回值的确可能是任意数据类型,才允许声明为mixed,否则一律禁止声明为mixed。
对于形参或返回值可能是多种数据类型的情况,必须将可能的数据类型全部列出(使用“|”分隔),如:file_put_contents(): int|false
多种数据类型返回值的处理:
以“file_put_contents(): int|false”为例,判断是否写入成功要用“$bytes !== false”,而不是“is_int($bytes)”。
异常和错误处理:
底层逻辑(如数据库读写、缓存读写等)如果出现异常或错误,必须记录错误信息(即写错误日志),并且向上逐层报错(return false/Exception),直到最顶层。
最顶层收到错误通知后,必须对错误进行处理,如显示系统异常页面(GET请求)或响应系统异常JSON字符串(POST请求)。
MVC模式细节:
使用单一模板:如article-add.php和article-edit.php两个页面,要使用同一个模板article-form.htm,并通过控制器传递$action变量(可选值:add=添加|edit=编辑)来区分操作。
基于角色的访问控制(RBAC)权限代码命名规则:
粒度1(小型系统):资源:操作,示例:product-category:edit(商品分类编辑权限)
粒度2(中型系统):模块:资源:操作
粒度3(大型系统):模块:子模块:资源类型:资源:操作
说明:根据系统的层次和复杂程度选择合适的粒度即可,注意尽量使用标准的、一致的动词来描述操作,如list(列表)、view(查看)、add(添加)、edit(编辑)、delete(删除)。
目录名用单数形式还是复数形式?
目录名统一使用单数形式,例如ThinkPHP项目的目录都是使用单数形式:
/app/controller:控制器目录
/app/model:模型目录
/config:配置目录
/view:视图目录
/route:路由定义目录
/public:WEB目录(对外访问目录)
/extend:扩展类库目录
/runtime:应用的运行时目录(可写,可定制)
/vendor:Composer类库目录
不同的框架有自己的命名规范,应该优先遵循框架规范,比起纠结使用单数形式还是复数形式,在项目中保持统一才是最重要的。
上传文件保存路径规则:/upload/分类/yyyyMM/dd/随机MD5字符串(英文字母全小写).ext
上传文件保存路径示例:/upload/img/200601/02/982cfa27c220e03587cb5ffc46d4e3e2.png
账号系统细节:
账号(用户名/邮箱)必须全程使用全小写,即注册时先转为全小写再写入数据库、登录时先转为全小写再查询数据库。
订单编号规则:
长度:20
格式:yyyyMMddHHmmss(14位)+随机数(6位,[0, 999999],不足6位左侧补零)
示例:20080808080808123456
软件版本号规则:
采用“x.y.z”三段式结构,其中x表示主版本号(Major),y表示次版本号(Minor),z表示修订号(Patch)。
主版本号(x)变化不保证兼容,API可能完全重构;次版本号(y)变化保证兼容,新增功能,旧接口仍可用;修订号(z)变化保证兼容,无功能变化,仅修复问题。
三段式版本号转纯数字版本ID公式:x * 10000 + y * 100 + z,如 5.6.40 = 5 * 10000 + 6 * 100 + 40 = 50640 ,比较版本新旧统一使用纯数字版本ID。
■ 数据库部分
对于经常出现在 WHERE / ORDER BY / GROUP BY / JOIN-ON 的字段,需重点考虑添加索引。
唯一索引名格式:unique:字段名1,字段名2,字段名3
普通索引名格式:index:字段名1,字段名2,字段名3
物理删除与逻辑删除使用建议:
对于核心业务表使用逻辑删除,如:用户表、产品表、产品分类表、订单表、……,其它非核心业务表使用物理删除。
细节①:禁止给is_deleted字段单独创建索引,如果有必要可以和其它字段组成联合索引,且不要将is_deleted字段作为联合索引首列,如:(`字段1`, `字段2`, `is_deleted`)。
细节②:禁止再次注册已逻辑删除的用户名,避免业务逻辑混乱,可向注册人反馈“该用户名已被注册”错误提示信息。