主题
CatchAdmin 开发约定
约定大于配置 - CatchAdmin 开发规范和最佳实践指南
约定大于配置是现代框架设计的核心理念。通过统一的约定,开发者能够快速理解项目结构,减少配置复杂度,提升开发效率。CatchAdmin 遵循这一理念,制定了一套简洁而实用的开发约定。
掌握这些约定将帮助你:
- 快速上手:无需大量配置即可开始开发
- 团队协作:统一的代码组织方式便于团队协作
- 维护便捷:标准化的结构降低维护成本
- 扩展灵活:约定化的架构支持功能快速扩展
📁 目录结构约定
后端模块位置
约定:所有后台业务功能模块统一放置在 modules
目录下
project/
├── modules/
│ ├── User/ # 用户管理模块
│ ├── Permissions/ # 权限管理模块
│ └── YourModule/ # 自定义模块
设计理念:
- 模块化开发,业务逻辑清晰分离
- 便于模块的独立开发、测试和维护
- 支持模块间的松耦合设计
前端页面位置
约定:模块对应的前端页面放置在 web/src/views
目录下
web/src/views/
├── user/ # 用户模块页面
├── permissions/ # 权限模块页面
└── your-module/ # 自定义模块页面
最佳实践:
- 前端目录名与后端模块名保持一致(小写)
- 页面组件按功能分组,保持结构清晰
- 遵循 Vue 3 单文件组件规范
🏷️ 枚举类型约定
枚举接口实现
约定:所有枚举类型必须实现 Catch\Enums\Enum
接口
php
<?php
namespace Modules\User\Enums;
use Catch\Enums\Enum;
enum UserStatus: int implements Enum
{
case ACTIVE = 1;
case INACTIVE = 2;
case BANNED = 3;
public function label(): string
{
return match($this) {
self::ACTIVE => '正常',
self::INACTIVE => '禁用',
self::BANNED => '封禁',
};
}
}
PHP 版本支持
CatchAdmin 要求 PHP 8.1+,因此可以充分利用 PHP 8.1 新增的枚举类型(enum)特性,提供类型安全和更好的代码提示。
枚举值约定
约定:整型枚举值从 1
开始
php
enum OrderStatus: int implements Enum
{
case PENDING = 1; // ✅ 从 1 开始
case CONFIRMED = 2;
case SHIPPED = 3;
case DELIVERED = 4;
}
为什么从 1 开始?
这个约定有重要的技术原因:
- 弱类型问题:PHP 中
0
、null
、""
在弱类型比较时相等 - 查询逻辑:枚举常用于数据库查询条件,从 1 开始避免了
WHERE status = 0
的歧义 - 前端处理:JavaScript 中也存在类似的类型转换问题
- API 设计:RESTful API 中,0 值容易与空值混淆
示例对比:
php
// 不推荐:从 0 开始可能导致逻辑错误
if ($status) { /* 当 status = 0 时,此条件为 false */ }
// 推荐:从 1 开始,逻辑清晰
if ($status) { /* 所有有效状态都会执行 */ }
🔧 公共功能约定
Common 模块设计
约定:通用功能统一放置在内置的 Common
模块中
包含功能:
- 文件上传:统一的文件上传接口和处理逻辑
- 枚举接口:为前端提供枚举值集合的 API 接口
- 通用工具:跨模块使用的工具类和辅助方法
- 系统配置:全局配置项的管理和读取
设计优势:
php
// Common 模块提供统一的上传服务
Route::post('/upload', [UploadController::class, 'handle']);
// 统一的枚举接口
Route::get('/enums/{enum}', [EnumController::class, 'get']);
这种设计避免了:
- 重复的上传逻辑在各模块中实现
- 枚举接口的分散管理
- 公共代码的冗余和不一致
🛣️ 路由管理约定
静态路由配置
约定:不使用动态菜单时,前端路由文件命名为 route.js
并放置在模块 views
目录下
web/src/views/user/
├── components/ # 组件目录
├── pages/ # 页面目录
│ ├── index.vue
│ └── detail.vue
└── route.js # 路由配置文件
路由文件示例:
javascript
// web/src/views/user/route.js
export default {
path: '/user',
name: 'User',
component: () => import('./pages/index.vue'),
meta: {
title: '用户管理',
requiresAuth: true
},
children: [
{
path: 'detail/:id',
name: 'UserDetail',
component: () => import('./pages/detail.vue')
}
]
}
适用场景:
- 模块路由相对固定,不需要动态配置
- 追求更好的类型提示和开发体验
- 需要精确控制路由的加载时机
参考示例
可以参考以下模块的实现:
develop
模块:开发工具相关路由user
模块:用户管理路由配置- 这些模块展示了静态路由的标准实现方式
💡 约定的价值
遵循 CatchAdmin 的开发约定能够:
- 提升开发效率:标准化的结构减少决策时间
- 降低学习成本:统一的模式便于新人快速上手
- 保证代码质量:约定化避免了常见的设计陷阱
- 促进团队协作:一致的代码风格提升协作效率
- 便于项目维护:清晰的结构降低维护复杂度
记住:约定不是限制,而是为了让开发变得更加简单和高效!