Skip to content

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 开始?

这个约定有重要的技术原因:

  1. 弱类型问题:PHP 中 0null"" 在弱类型比较时相等
  2. 查询逻辑:枚举常用于数据库查询条件,从 1 开始避免了 WHERE status = 0 的歧义
  3. 前端处理:JavaScript 中也存在类似的类型转换问题
  4. 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 的开发约定能够:

  1. 提升开发效率:标准化的结构减少决策时间
  2. 降低学习成本:统一的模式便于新人快速上手
  3. 保证代码质量:约定化避免了常见的设计陷阱
  4. 促进团队协作:一致的代码风格提升协作效率
  5. 便于项目维护:清晰的结构降低维护复杂度

记住:约定不是限制,而是为了让开发变得更加简单和高效!