如何使用AI开发iCMS8应用,完整提示词规范

iCMS8 前后端应用开发规范

一、项目概述

1.1 技术栈

  • 后端框架: iPHP (自研PHP框架)
  • 数据库: MySQL 5.0+
  • 前端: HTML + JavaScript + Vue.js (部分模块)
  • 模板引擎: TemplateLite (类Smarty)
  • 支持特性: 多语言、分表分库、事件驱动、缓存系统

1.2 核心特点

  • MVC架构模式
  • 模块化应用设计
  • 国际化(i18n)支持
  • RESTful路由
  • 事件钩子机制
  • 数据模型ORM

二、应用目录结构规范

2.1 标准应用目录结构

app/[应用名]/
├── [App]Model.php # 数据模型 (必需)
├── [App]DataModel.php # 数据表模型 (可选,用于分表)
├── [App]Admincp.php # 后台控制器 (必需)
├── [App]App.php # 前台控制器 (必需)
├── [App]UserApp.php # 用户中心控制器 (可选)
├── [App]Func.php # 模板标签函数 (必需)
├── [App]Hook.php # 钩子文件 (可选)
├── [App]Event.php # 事件处理 (可选)
├── assets/ # 静态资源
│ ├── js/ # JavaScript文件
│ └── *.css # CSS样式文件
├── etc/ # 配置目录
│ ├── lang/ # 多语言配置
│ │ ├── zh-cn.json # 通用语言包
│ │ ├── zh-cn.admincp.json # 后台语言包
│ │ └── zh-cn.usercp.json # 前台语言包
│ ├── menu/ # 菜单配置
│ ├── route/ # 路由配置
│ └── config/ # 应用配置
└── views/ # 后台视图模板
├── index.html # 列表页
├── add.html # 添加页
├── edit.html # 编辑页
└── app/ # 其他视图

---

## 三、后端开发规范

### 3.1 Model 数据模型开发

#### 3.1.1 基础模型结构
```php
<?php
defined('iPHP') or exit('What are you doing?');

class ArticleModel extends Model
{
    // 状态映射
    public static $statusMap = [
        '0' => '草稿',
        '1' => '正常',
        '2' => '回收站',
    ];

    // 字段类型转换
    protected $casts = [
        'picdata' => 'array',
        'nodeAttrs' => 'array',
    ];

    // 事件绑定
    protected $events = [
        'delete' => ['ArticleEvent', 'delete'],
        'changed' => ['ArticleEvent', 'changed'],
    ];
}

3.1.2 数据模型关键属性

  • $statusMap: 状态映射数组
  • $casts: 字段类型自动转换 (array, json, html等)
  • $events: 模型事件绑定
  • $callback: 异常回调处理

3.1.3 分表模型 (DataModel)

class ArticleDataModel extends Model
{
    // 分表策略
    public static function sharding($article_id)
    {
        $model = self::getInstance();
        $model->sharding = (int)$article_id % 10;
        return $model;
    }

    // 自动创建表
    protected $callback = [
        'SQLSTATE:42S02' => [__CLASS__, 'createTable'],
    ];
}

3.2 Admincp 后台控制器开发

iCMS8 提供了三种后台应用开发模式,根据功能需求选择合适的开发方式。

3.2.1 模式一:标准 CRUD 应用开发 ⭐ 推荐

适用场景: 需要完整增删改查(CRUD)功能的应用模块,如文章管理、用户管理、商品管理等。

开发方式:

<?php
defined('iPHP') or exit('What are you doing?');
defined('APP_URL') or define('APP_URL', '/admincp.php/article');

class ArticleAdmincp extends AdmincpCommon
{
    use AdmincpCommonTrait;  // 关键:使用 Trait

    // 排序字段配置
    public static $orderBy = [
        'id'         => 'ID',
        'hits'       => '点击',
        'postime'    => '时间',
        'weight'     => '权重',
    ];
}

核心特点:

  • 自动继承功能: 通过 AdmincpCommonAdmincpCommonTrait,自动获得完整的增删改查、批量操作、状态管理等功能
  • 快速开发: 只需绑定模型类,即可快速实现数据管理功能
  • 扩展性强: 可以通过重写 Trait 中的方法实现自定义逻辑

自动提供的功能:

  • 列表展示 (do_index())
  • 添加/编辑 (do_add())
  • 保存数据 (do_save())
  • 删除操作 (do_delete())
  • 批量操作 (do_batch())
  • 状态管理 (do_status())
  • 排序管理 (do_sort())

自定义扩展示例:

class ArticleAdmincp extends AdmincpCommon
{
    use AdmincpCommonTrait;

    /**
     * 保存前数据处理
     */
    protected function saving(&$data)
    {
        // 自动设置编辑者
        if (empty($this->id)) {
            $data['editor'] = Admin::$nickname;
            $data['userid'] = Admin::$user_id;
        }

        // 数据验证
        empty($data['title']) && self::alert('标题不能为空');

        // 自动生成摘要
        if (empty($data['description'])) {
            $data['description'] = mb_substr(strip_tags($data['content']), 0, 200);
        }

        // 返回 true 表示验证通过
        return true;
    }

    /**
     * 列表数据处理
     */
    protected function index_data(&$resource)
    {
        foreach ($resource as &$item) {
            // 添加自定义字段
            $item['category_name'] = CategoryModel::getValue($item['cid'], 'name');
        }
    }

    /**
     * 自定义添加/编辑页面
     */
    public function do_add()
    {
        // 获取数据
        $rs = $this->id ? ArticleModel::get($this->id) : [];

        // 初始化默认值
        if (empty($this->id)) {
            $rs['status'] = '1';
            $rs['postype'] = '1';
        }

        // 加载视图
        include self::view();
    }
}

3.2.2 模式二:简单功能应用开发

适用场景: 仅需基础功能(如列表查看、详情展示)的应用模块,如文件管理、日志查看等。

开发方式:

<?php
defined('iPHP') or exit('What are you doing?');

class FilesAdmincp extends AdmincpCommon
{
    // 注意:不使用 AdmincpCommonTrait

    /**
     * 列表页
     */
    public function do_index()
    {
        $where = [];
        $model = FilesModel::field('*');

        // 条件筛选
        $keyword = Request::get('keyword');
        $keyword && $where[] = ['name', 'LIKE', "%{$keyword}%"];

        // 查询数据
        $resource = $model->where($where)
            ->orderBy('id', 'DESC')
            ->paginate(20);

        include self::view();
    }

    /**
     * 详情页
     */
    public function do_view()
    {
        $id = Request::get('id');
        $file = FilesModel::get($id);

        include self::view();
    }
}

核心特点:

  • 轻量级: 仅继承 AdmincpCommon,不引入 AdmincpCommonTrait,减少不必要的功能
  • 功能精简: 默认支持列表查看和详情展示,无需额外编码
  • 可配置性: 通过覆盖方法或配置属性,可以禁用不需要的功能

适用场景:

  • 仅需查看数据列表或详情,无需编辑、删除等操作
  • 功能简单,不需要复杂的业务逻辑
  • 只读型数据管理

3.2.3 模式三:基础定制应用开发

适用场景: 需要完全自定义功能逻辑的应用模块,如系统配置、特殊功能模块等。

开发方式:

<?php
defined('iPHP') or exit('What are you doing?');

class ConfigAdmincp extends AdmincpBase
{
    // 完全自定义功能

    /**
     * 配置页面
     */
    public function do_index()
    {
        // 获取配置
        $config = ConfigModel::getAll();

        include self::view();
    }

    /**
     * 保存配置
     */
    public function do_save()
    {
        $data = Request::post('config');

        // 自定义验证逻辑
        empty($data['site_name']) && self::alert('网站名称不能为空');

        // 自定义保存逻辑
        foreach ($data as $key => $value) {
            ConfigModel::set($key, $value);
        }

        // 清除缓存
        Cache::delete('config');

        // 返回成功
        return [true, '保存成功'];
    }

    /**
     * 清理缓存
     */
    public function do_clear_cache()
    {
        Cache::flush();
        return [true, '缓存已清理'];
    }
}

核心特点:

  • 完全自主: 继承 AdmincpBase,不依赖 AdmincpCommon 和 Trait,开发者可以完全自定义功能逻辑
  • 灵活性高: 适合需要特殊处理或复杂业务逻辑的场景
  • ⚠️ 手动实现: 需要开发者手动实现数据管理、权限控制等功能

适用场景:

  • 需要完全自定义的功能模块
  • 功能逻辑复杂,无法通过标准 CRUD 模式实现
  • 系统级配置管理

3.2.4 开发模式对比

特性 标准 CRUD 简单功能 基础定制
继承类 AdmincpCommon AdmincpCommon AdmincpBase
使用 Trait ✅ AdmincpCommonTrait
自动 CRUD ✅ 完整支持 ⚠️ 需手动实现 ❌ 需手动实现
批量操作 ✅ 自动支持
开发效率 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
灵活性 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
适用场景 数据管理 只读查看 特殊功能

3.2.5 选择建议

  1. 标准 CRUD 应用 ⭐ 推荐

    • 适用于大多数数据管理场景
    • 功能全面,开发效率高
    • 90% 的后台应用都应该使用此模式
  2. 简单功能应用

    • 适用于只读型数据管理
    • 功能精简,适合快速实现
    • 如日志查看、文件浏览等
  3. 基础定制应用

    • 适用于特殊功能模块
    • 灵活性高,适合复杂业务逻辑
    • 如系统配置、工具类应用等

3.2.6 关键方法命名规范

无论使用哪种模式,方法命名都遵循以下规范:

  • do_index(): 列表页面
  • do_add(): 添加/编辑页面
  • do_save(): 保存数据
  • do_delete(): 删除操作
  • do_batch(): 批量操作
  • do_status(): 状态修改
  • do_sort(): 排序操作
  • *done_()**: AJAX 数据接口(返回 JSON)

3.2.7 响应方式详解

iCMS8 提供了灵活的响应机制,支持多种返回方式。

错误响应:

// 方式1: 使用 self::alert() - 推荐
empty($data['title']) && self::alert('标题不能为空');

// 方式2: 直接返回 false
if (empty($data['title'])) {
    return false;  // 自动显示错误
}

// 方式3: 返回错误信息数组
return [false, '操作失败', $url];

成功响应:

// 方式1: 返回 true
return true;  // 自动显示成功

// 方式2: 返回成功信息数组
return [true, '保存成功'];
return [true, '保存成功', $url];  // 带跳转URL

// 方式3: 返回 null (POST请求时)
return null;  // POST请求自动返回成功

// 方式4: 返回数据数组
return [
    'code' => 1,
    'state' => 'SUCCESS',
    'message' => '操作成功',
    'url' => APP_URL,
    'data' => ['id' => $id]
];

// 方式5: 返回数字
return $id;  // 返回ID,大于0表示成功

// 方式6: 返回URL字符串
return 'http://example.com';  // 自动跳转
return '/article/list';  // 相对路径跳转
return 'url:/article/list:2000';  // 延迟2秒跳转

AJAX/API 响应:

// 使用 iJson 类
public function done_get_data()
{
    $id = Request::get('id');
    $data = ArticleModel::get($id);

    if ($data) {
        // 成功响应
        iJson::success($data, '获取成功');
    } else {
        // 失败响应
        iJson::error('数据不存在', '', 404);
    }
}

// 或者直接返回数据
public function done_list()
{
    $list = ArticleModel::limit(10)->select();
    return $list;  // 自动转为 JSON
}

响应参数说明:

// 数组响应格式
[
    'code' => 1,              // 状态码: 1=成功, 0=失败
    'state' => 'SUCCESS',     // 状态: SUCCESS/ERROR
    'message' => '提示信息',   // 提示消息
    'url' => '跳转地址',       // 跳转URL(可选)
    'data' => []              // 返回数据(可选)
]

// iJson 方法
iJson::success($data, $message, $url, $code, $state);
iJson::error($message, $url, $code, $state);
iJson::fail($message, $url, $code, $state);

实际应用示例:

class ArticleAdmincp extends AdmincpCommon
{
    use AdmincpCommonTrait;

    // 保存前验证
    protected function saving(&$data)
    {
        empty($data['title']) && self::alert('标题不能为空');
        empty($data['cid']) && self::alert('请选择栏目');

        // 重复检查
        if (ArticleModel::check($data['title'], $data['id'])) {
            self::alert('该标题已存在');
        }

        return true;  // 验证通过
    }

    // 删除操作
    public function do_delete()
    {
        $this->id or self::alert('请选择要删除的文章');
        ArticleModel::delete($this->id);
        return [true, '删除成功', APP_URL];
    }

    // AJAX获取数据
    public function done_get_article()
    {
        $id = Request::get('id');
        $id or iJson::error('参数错误');

        $article = ArticleModel::get($id);
        $article or iJson::error('文章不存在', '', 404);

        iJson::success($article, '获取成功');
    }
}

### 3.3 App 前台控制器开发

前台控制器继承 `AppsBase` 并使用 `AppsAppTrait`,提供三种方法类型来处理不同的请求场景。

#### 3.3.1 三种方法类型

**方法命名规范**:
- `do_*()`: 页面渲染方法(有模板输出)
- `api_*()`: API 接口方法(返回 JSON)
- `display()`: 通用展示方法(供路由调用)

---

#### 3.3.2 类型一:页面渲染方法 (do_*)

**适用场景**: 需要渲染 HTML 模板的页面,如详情页、列表页等。

**访问方式**: `api.php/应用名/方法名?参数`

**示例代码**:
```php
<?php
class ArticleApp extends AppsBase
{
    use AppsAppTrait;

    protected static $DATA = [];

    /**
     * 详情页
     * 访问: api.php/article/detail?id=1
     */
    public function do_detail($id = null, $tpl = null)
    {
        // 获取参数
        $id === null && $id = (int)Request::get('id');

        // 查询数据
        $article = ArticleModel::where([
            'id' => $id,
            'status' => 1
        ])->find();

        // 数据验证
        empty($article) && self::alert(['errors:not_found', [self::$app, 'id', $id]], 10001);

        // 处理数据
        $vars = ['tag' => true, 'user' => true];
        self::values($article, $vars, $tpl);

        // 获取正文数据
        $articleData = ArticleDataModel::sharding($id)
            ->where('article_id', $id)
            ->first();
        $article['body'] = $articleData['body'];

        // 渲染模板
        $tpl === null && $tpl = self::$DATA['node']['template']['article:detail'];
        return self::render($article, $tpl);
    }

    /**
     * 列表页
     * 访问: api.php/article/list?cid=1&page=1
     */
    public function do_list($cid = null, $tpl = null)
    {
        $cid === null && $cid = (int)Request::get('cid');
        $page = (int)Request::get('page', 1);

        // 查询列表
        $_GET['page'] = $page;
        $articles = ArticleModel::where([
            'cid' => $cid,
            'status' => 1
        ])->orderBy('id', 'DESC')->paging(20);

        // 处理数据
        foreach ($articles as &$item) {
            self::values($item, ['tag' => false], false);
        }

        // 渲染模板
        $tpl === null && $tpl = 'article_list.htm';
        return self::render([
            'list' => $articles,
            'total' => Paging::$total,
            'page' => $page
        ], $tpl);
    }
}

核心方法:

  • $this->getData($value, $field, $tpl): 获取数据(继承自 AppsAppTrait)
  • self::render($data, $tpl): 渲染模板
  • self::values(&$data, $vars, $tpl): 数据处理

3.3.3 类型二:API 接口方法 (api_*)

适用场景: 提供 JSON 数据接口,用于 AJAX 请求、小程序、APP 等。

访问方式: api.php/应用名/方法名?参数

返回格式: 自动转换为 JSON

示例代码:

class ArticleApp extends AppsBase
{
    use AppsAppTrait;

    /**
     * 获取文章列表(API)
     * 访问: api.php/article/get_list?page=1&pageSize=10
     */
    public function api_get_list()
    {
        $page = Request::get('page', 1);
        $pageSize = Request::get('pageSize', 10);
        $cid = Request::get('cid', 0);

        $_GET['page'] = $page;

        // 构建查询
        $where = ['status' => 1];
        $cid && $where['cid'] = $cid;

        $obj = ArticleModel::where($where);
        $obj->orderBy('id', 'DESC');
        $rows = $obj->paging($pageSize);

        // 处理数据
        foreach ($rows as &$item) {
            $item['url'] = Route::get('article', [$item])->href;
            $item['pic'] = FilesPic::getArray($item['pic']);
        }

        // 返回数据(自动转 JSON)
        return [
            'list' => $rows,
            'total' => Paging::$total,
            'page' => $page,
            'pageSize' => $pageSize
        ];
    }

    /**
     * 获取文章详情(API)
     * 访问: api.php/article/get_detail?id=1
     */
    public function api_get_detail()
    {
        $id = (int)Request::get('id');
        $id or iJson::error('参数错误');

        $article = ArticleModel::get($id);
        $article or iJson::error('文章不存在', '', 404);

        // 获取正文
        $articleData = ArticleDataModel::sharding($id)
            ->where('article_id', $id)
            ->first();

        $article['body'] = $articleData['body'];
        $article['url'] = Route::get('article', [$article])->href;

        return $article;
    }

    /**
     * 提交评论(API)
     * 访问: api.php/article/submit_comment
     */
    public function api_submit_comment()
    {
        $data = [
            'userid' => User::$id,
            'article_id' => Request::post('article_id'),
            'content' => Request::post('content'),
            'ip' => Request::ip(),
            'created' => $_SERVER['REQUEST_TIME'],
        ];

        // 验证
        empty($data['content']) && iJson::error('评论内容不能为空');
        User::$id or iJson::error('请先登录');

        // 保存
        CommentModel::create($data);

        return [true, '评论成功!'];
    }
}

返回方式:

// 方式1: 返回数组(推荐)
return ['key' => 'value'];

// 方式2: 使用 iJson
iJson::success($data, '成功信息');
iJson::error('错误信息', '', 404);

// 方式3: 返回成功/失败
return [true, '操作成功'];
return [false, '操作失败'];

3.3.4 类型三:通用展示方法 (display)

适用场景: 供路由系统或其他代码调用的通用方法。

调用方式:

  • 路由自动调用
  • 代码调用: (new ArticleApp())->display($id)

示例代码:

class ArticleApp extends AppsBase
{
    use AppsAppTrait;

    /**
     * 通用展示方法
     * 供路由或其他地方调用
     */
    public function display($value, $field = 'id', $tpl = true)
    {
        $vars = ['tag' => true, 'user' => true];

        // 获取主表数据
        $article = $this->getData($value, $field, $tpl);
        if ($article === false) {
            return false;
        }

        // 获取扩展表数据
        $articleData = ArticleDataModel::sharding($article['id'])
            ->field('body, subtitle')
            ->where('article_id', $article['id'])
            ->first();

        // 处理数据
        self::values($article, $articleData, $vars, $tpl);
        self::getCustomData($article, $vars);

        // 渲染
        return self::render($article, $tpl);
    }
}

3.3.5 数据处理方法 (values)

作用: 处理数据,添加通用字段(URL、用户信息、图片等)。

示例代码:

/**
 * 静态方法:数据处理
 * @param array $article 主表数据
 * @param array $data 扩展数据
 * @param array $vars 变量配置
 * @param mixed $tpl 模板
 */
public static function values(&$article, $data = null, $vars = [], $tpl = false)
{
    // 初始化
    self::initialize($article, $tpl);

    // 处理扩展数据
    if ($data) {
        $article['body'] = $data['body'];
        $article['subtitle'] = $data['subtitle'];
    }

    // 状态文本
    $article['statusText'] = ArticleModel::$statusMap[$article['status']];

    // 处理标签
    $vars['tag'] && TagApp::getArray($article, $article['node']['name'], 'tags');

    // 使用 AppsCommon 处理通用数据
    AppsCommon::init($article, $vars)
        ->link()      // 生成 URL 和 link
        ->user()      // 处理用户信息
        ->comment()   // 处理评论数
        ->pic()       // 处理图片
        ->hits()      // 处理点击数
        ->params();   // 处理参数

    return $article;
}

AppsCommon 链式方法:

  • ->link(): 生成 urllink 字段
  • ->user(): 添加用户信息(需要 $vars['user'] = true
  • ->comment(): 添加评论数
  • ->pic(): 处理图片字段
  • ->hits(): 处理点击数
  • ->params(): 处理自定义参数
  • ->text2link(): 文本转链接(可选)

3.3.6 访问路径说明

方法类型 方法名示例 访问路径 说明
do_* do_detail() api.php/article/detail?id=1 页面渲染
do_* do_list() api.php/article/list?cid=1 列表页
api_* api_get_list() api.php/article/get_list JSON接口
api_* api_submit() api.php/article/submit 提交接口
display() display($id) 路由调用或代码调用 通用方法

3.3.7 重要提示

  1. 方法命名: do_ 用于页面,api_ 用于接口
  2. 参数处理: 使用 Request::get() / Request::post()
  3. 数据验证: 空数据使用 self::alert() 返回错误
  4. 模板渲染: 使用 self::render()
  5. API返回: 返回数组,系统自动转 JSON
  6. 静态方法: 供模板标签或其他地方调用
  7. 链式调用: 使用 AppsCommon::init()->link()->user()->...
  8. HTTPS处理: 注意资源URL的协议转换

3.4 Func 模板标签开发

3.4.1 标准结构

<?php
class ArticleFunc extends AppsFuncCommon implements AppsFuncInterface
{
    /**
     * 列表标签
     * 用法: {iCMS:article:list loop="true" row="10"}
     */
    public static function lists($vars)
    {
        $model = ArticleModel::field('id');
        $where = [['status', 1]];

        // 条件处理
        isset($vars['cid']) && $where[] = ['cid', $vars['cid']];
        isset($vars['userid']) && $where[] = ['userid', $vars['userid']];

        self::inited($vars, $model, $where);
        self::nodes('cid');
        self::tags();
        self::orderby();

        return self::getResource(__METHOD__);
    }

    /**
     * 资源处理
     */
    public static function resource($idsArray = null)
    {
        $resource = ArticleModel::field('*')
            ->where($idsArray)
            ->select();
        return self::many(self::$vars, $resource);
    }
}

四、前端开发规范

4.1 后台视图模板 (views/*.html)

4.1.1 列表页模板 (index.html)

<?php
defined('iPHP') or exit('What are you doing?');
self::head();
?>
<div class="content">
    <div class="block">
        <div class="block-header">
            <h3 class="block-title"><?=Lang('admincp:article:list')?></h3>
            <div class="block-options">
                <a href="<?=APP_URL?>/add" class="btn btn-primary">
                    <i class="fa fa-plus"></i> <?=Lang('admincp:btn:add')?>
                </a>
            </div>
        </div>
        <div class="block-content">
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th><?=Lang('fields:id')?></th>
                        <th><?=Lang('fields:title')?></th>
                        <th><?=Lang('fields:status')?></th>
                        <th><?=Lang('admincp:action')?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach($resource as $item): ?>
                    <tr>
                        <td><?=$item['id']?></td>
                        <td><?=$item['title']?></td>
                        <td><?=$item['statusText']?></td>
                        <td>
                            <a href="<?=APP_URL?>/add&id=<?=$item['id']?>">
                                <?=Lang('admincp:btn:edit')?>
                            </a>
                        </td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </div>
</div>

4.1.2 添加/编辑页模板 (add.html)

<form action="<?=APP_DOURL?>" method="POST" i="cms:ui:form">
    <input name="rs[id]" type="hidden" value="<?=$this->id?>" />

    <div class="form-floating mb-3">
        <input type="text" name="rs[title]" class="form-control" 
               value="<?=$rs['title']?>" data-rule="required" />
        <label><?=Lang('fields:title')?></label>
    </div>

    <div class="form-group">
        <label><?=Lang('fields:content')?></label>
        <textarea name="rs[content]" class="form-control" rows="10">
            <?=$rs['content']?>
        </textarea>
    </div>

    <button type="submit" class="btn btn-primary">
        <i class="fa fa-check"></i> <?=Lang('admincp:btn:submit')?>
    </button>
</form>

4.2 前端模板标签使用

4.2.1 模板系统概述

模板边界符: <!--{...}-->

基本特性:

  • 基于 Template Lite 模板引擎
  • 兼容 80% 以上 Smarty 语法
  • 采用 HTML 注释形式的边界符
  • 执行效率高,支持多种高级模板特性

4.2.2 变量输出

基本变量:

<!--{$variable}-->

数组变量:

<!--{$array.key}-->
<!--{$array[0]}-->
<!--{$array.arr.key}-->

复合变量:

<!--{$var1$var2$var3'text'123}-->

4.2.3 条件判断

<!--{if $article.status == 1}-->
    <span class="badge bg-success">已发布</span>
<!--{elseif $article.status == 0}-->
    <span class="badge bg-warning">待审核</span>
<!--{else}-->
    <span class="badge bg-danger">已删除</span>
<!--{/if}-->

4.2.4 循环结构

foreach 循环:

<!--{foreach $articles as $article}-->
    <div class="article-item">
        <h3><!--{$article.title}--></h3>
        <p><!--{$article.description}--></p>
    </div>
<!--{/foreach}-->

for 循环:

<!--{for $i=0; $i<10; $i++}-->
    <div>第 <!--{$i}--> 项</div>
<!--{/for}-->

4.2.5 应用标签调用

标签格式:

<!--{iCMS:应用名:方法名 参数='值'}-->

单次调用(不循环):

<!--{iCMS:article:data aid='1' cache='1'}-->
<div class="article-content">
    <h1><!--{$article_data.title}--></h1>
    <div class="content"><!--{$article_data.body}--></div>
</div>

循环调用(loop='true'):

<!--{iCMS:article:list loop='true' row='10' cid='1'}-->
    <div class="article-item">
        <h3><a href="<!--{$article_list.url}-->"><!--{$article_list.title}--></a></h3>
        <p><!--{$article_list.description}--></p>
    </div>
<!--{iCMSelse}-->
    <p>暂无内容</p>
<!--{/iCMS}-->

自定义变量名(as="别名"):

<!--{iCMS:article:list loop='true' row='10' as='art'}-->
    <div class="article-item">
        <h3><a href="<!--{$art.url}-->"><!--{$art.title}--></a></h3>
        <p><!--{$art.description}--></p>
    </div>
<!--{/iCMS}-->

4.2.6 文章标签示例

文章列表:

<!--{iCMS:article:list loop='true' row='10' cid='1' orderby='id' order='desc'}-->
<div class="article-item">
    <div class="article-thumb">
        <a href="<!--{$article_list.url}-->">
            <img src="<!--{$article_list.pic.0.url}-->" alt="<!--{$article_list.title}-->">
        </a>
    </div>
    <div class="article-info">
        <h3><a href="<!--{$article_list.url}-->"><!--{$article_list.title}--></a></h3>
        <div class="meta">
            <span><!--{$article_list.pubdate|date:'Y-m-d H:i:s'}--></span>
            <span><!--{$article_list.hits}--> 阅读</span>
        </div>
        <p><!--{$article_list.description}--></p>
    </div>
</div>
<!--{iCMSelse}-->
<p class="text-center">暂无相关内容</p>
<!--{/iCMS}-->

分页:

<!--{iCMS:article:list loop='true' row='10' page='1'}-->
    <!-- 列表内容 -->
<!--{/iCMS}-->

<!--{iCMS:pages page_style='3' item='<li class="page-item %s">%s</li>' link='<a class="page-link" href="%s" data-pageno="%d" %s>%s</a>'}-->
<nav aria-label="Page navigation">
    <ul class="pagination justify-content-center">
        <!--{$iCMS.PAGE.NAV}-->
    </ul>
</nav>

文章详情:

<!--{iCMS:article:data aid='$article.id' cache='1'}-->
<article class="article-detail">
    <h1><!--{$article_data.title}--></h1>
    <!--{if $article_data.subtitle}-->
    <h2 class="subtitle"><!--{$article_data.subtitle}--></h2>
    <!--{/if}-->
    <div class="article-meta">
        <span>作者: <!--{$article.author}--></span>
        <span>发布时间: <!--{$article.pubdate|date:'Y-m-d H:i:s'}--></span>
        <span>阅读: <!--{$article.hits}--></span>
    </div>
    <div class="article-body">
        <!--{$article_data.body}-->
    </div>
</article>

上一篇/下一篇:

<!--{iCMS:article:prev aid='$article.id' cid='$article.cid'}-->
<a href="<!--{$article_prev.url}-->" class="btn btn-prev">
    上一篇: <!--{$article_prev.title}-->
</a>
<!--{/iCMS}-->

<!--{iCMS:article:next aid='$article.id' cid='$article.cid'}-->
<a href="<!--{$article_next.url}-->" class="btn btn-next">
    下一篇: <!--{$article_next.title}-->
</a>
<!--{/iCMS}-->

4.2.7 栏目标签示例

栏目列表:

<!--{iCMS:article:category loop='true' stype='top' row='10'}-->
<div class="category-item">
    <h3><a href="<!--{$article_category.url}-->"><!--{$article_category.name}--></a></h3>
    <p><!--{$article_category.description}--></p>
    <span>文章数: <!--{$article_category.count}--></span>
</div>
<!--{/iCMS}-->

栏目树形结构:

<!--{iCMS:node:list loop='true' stype='top' appid='article'}-->
<li>
    <a href="<!--{$node_list.url}-->"><!--{$node_list.name}--></a>
    <!--{if $node_list.child}-->
    <ul>
        <!--{foreach $node_list.child as $sub}-->
        <li><a href="<!--{$sub.url}-->"><!--{$sub.name}--></a></li>
        <!--{/foreach}-->
    </ul>
    <!--{/if}-->
</li>
<!--{/iCMS}-->

4.2.8 标签嵌套使用

栏目+文章嵌套:

<!--{iCMS:article:category stype='top' row='5'}-->
<div class="category-section">
    <h2><a href="<!--{$article_category.url}-->"><!--{$article_category.name}--></a></h2>

    <!--{iCMS:article:list cid='$article_category.id' row='3' cache='1'}-->
    <ul class="article-list">
        <li><a href="<!--{$article_list.url}-->"><!--{$article_list.title}--></a></li>
    </ul>
    <!--{/iCMS}-->
</div>
<!--{/iCMS}-->

变量传递(在文章详情页):

<h1><!--{$article.title}--></h1>
<div class="content"><!--{$article.body}--></div>

<!-- 相关文章 -->
<!--{iCMS:article:list loop='1' cid='$article.cid' id!='$article.id' row='5'}-->
<div class="related">
    <h3>相关文章</h3>
    <ul>
        <li><a href="<!--{$article_list.url}-->"><!--{$article_list.title}--></a></li>
    </ul>
</div>
<!--{/iCMS}-->

4.2.9 常用标签参数

article:list 参数:

  • loop='true': 循环输出
  • row='10': 获取数量
  • cid='1': 栏目ID
  • page='1': 分页
  • orderby='id': 排序字段
  • order='desc': 排序方式
  • status='1': 状态筛选
  • userid='1': 用户ID筛选
  • tags='标签': 标签筛选
  • cache='1': 缓存时间(秒)
  • as='art': 自定义变量名

article:category 参数:

  • loop='true': 循环输出
  • stype='top': 顶级栏目
  • stype='sub': 子栏目
  • pid='1': 父栏目ID
  • row='10': 获取数量

node:list 参数:

  • loop='true': 循环输出
  • appid='article': 应用ID
  • stype='top': 顶级节点
  • pid='0': 父节点ID
  • row='10': 获取数量

4.2.10 重要提示

  1. 边界符: 必须使用 <!--{...}--> 格式
  2. 变量输出: <!--{$variable}-->
  3. 标签格式: <!--{iCMS:app:method param='value'}-->
  4. 循环标签: 必须添加 loop='true' 参数
  5. 自定义变量: 使用 as='别名' 参数
  6. 条件判断: 使用 <!--{if}-->...<!--{/if}-->
  7. 空数据处理: 使用 <!--{iCMSelse}--> 显示默认内容
  8. 变量传递: 外层标签变量可用 $ 引用传递给内层

4.3 模板辅助方法

iCMS 提供了丰富的模板方法,包括 调节器块处理器函数处理器,用于在模板中对数据进行处理和展示。

4.3.1 调节器 (Modifier)

调节器用于对模板变量进行处理,形式为 <!--{$变量|调节器}-->

常用调节器:

调节器 说明 示例
date 格式化日期 ``
cut 截取字符串 ``
truncate 截取字符串(智能) ``
upper 转大写 ``
lower 转小写 ``
capitalize 首字母大写 ``
replace 替换字符串 ``
default 设置默认值 ``
escape HTML转义 ``
json JSON编码 ``
markdown Markdown解析 ``
pinyin 转拼音 ``
thumb 生成缩略图 ``
print_r 调试输出 ``

字符串处理:

<!-- 截取字符串 -->
<!--{$article.title|cut:20:'...'}-->

<!-- 转大写 -->
<!--{$str|upper}-->

<!-- 替换内容 -->
<!--{$content|replace:'旧内容':'新内容'}-->

<!-- 设置默认值 -->
<!--{$description|default:'暂无描述'}-->

<!-- HTML转义 -->
<!--{$user_input|escape:'html'}-->

日期处理:

<!-- 格式化日期 -->
<!--{$article.pubdate|date:'Y-m-d H:i:s'}-->
<!--{$article.pubdate|date:'Y年m月d日'}-->
<!--{$article.created|date:'m/d/Y'}-->

数组处理:

<!-- 提取数组列 -->
<!--{$articles|pluck:'title'}-->

<!-- 提取指定字段 -->
<!--{$data|fields:'id,title,url'}-->

<!-- 提取键名 -->
<!--{$array|keys:'key1,key2':true}-->

<!-- JSON编码 -->
<!--{$data|json}-->

图片处理:

<!-- 生成缩略图 -->
<img src="<!--{$article.pic.0.url|thumb:300:200}-->" alt="<!--{$article.title}-->">

<!-- 不同尺寸 -->
<!--{$image|thumb:100:100}--> <!-- 100x100 -->
<!--{$image|thumb:200:150}--> <!-- 200x150 -->

高级用法:

<!-- 链式调用 -->
<!--{$article.title|cut:30:'...'|upper}-->

<!-- 调用对象方法 -->
<!--{$object|call:'method':'arg1':'arg2'}-->

<!-- Markdown解析 -->
<!--{$article.body|markdown}-->

<!-- 拼音转换 -->
<!--{$title|pinyin:'-'}--> <!-- 输出: zhong-wen-biao-ti -->

4.3.2 块处理器 (Block)

块处理器用于处理模板中的块内容,形式为 <!--{block}-->内容<!--{/block}-->

cache - 缓存块:

<!-- 缓存3600秒 -->
<!--{cache id="sidebar" time="3600"}-->
<div class="sidebar">
    <!--{iCMS:article:list row='5'}-->
        <li><!--{$article_list.title}--></li>
    <!--{/iCMS}-->
</div>
<!--{/cache}-->

capture - 捕获块:

<!-- 捕获内容到变量 -->
<!--{capture name="page_title"}-->
    <!--{$article.title}--> - <!--{'site_name'|lang}-->
<!--{/capture}-->

<!-- 使用捕获的内容 -->
<title><!--{$page_title}--></title>

strip - 去除空格:

<!-- 去除多余空格和换行 -->
<!--{strip}-->
<div>
    <span>内容</span>
    <span>内容</span>
</div>
<!--{/strip}-->

<!-- 输出: <div><span>内容</span><span>内容</span></div> -->

textformat - 文本格式化:

<!-- 格式化为邮件样式 -->
<!--{textformat style="email"}-->
这是一段很长的文本内容,会被自动格式化为适合邮件显示的格式。
<!--{/textformat}-->

4.3.3 函数处理器 (Function)

函数处理器用于在模板中调用函数,形式为 <!--{function 参数}-->

array - 创建数组:

<!--{array as="colors" red="红色" blue="蓝色" green="绿色"}-->
<!--{foreach $colors as $key => $value}-->
    <span><!--{$key}-->: <!--{$value}--></span>
<!--{/foreach}-->

rand - 随机选择:

<!-- 随机选择一个值 -->
<!--{rand values="1,2,3,4,5" as="random"}-->
<div>随机数: <!--{$random}--></div>

counter - 计数器:

<!-- 从1开始,每次增加2 -->
<!--{foreach $articles as $article}-->
    <!--{counter start=1 skip=2}--> <!--{$article.title}-->
<!--{/foreach}-->

cycle - 循环值:

<!-- 循环使用不同的CSS类 -->
<!--{foreach $articles as $article}-->
    <div class="<!--{cycle values='odd,even'}-->">
        <!--{$article.title}-->
    </div>
<!--{/foreach}-->

math - 数学运算:

<!-- 计算总价 -->
<!--{math equation="price * quantity" price=$item.price quantity=$item.quantity assign="total"}-->
<span>总价: <!--{$total}--></span>

<!-- 计算百分比 -->
<!--{math equation="(current / total) * 100" current=50 total=200 assign="percent"}-->
<span>进度: <!--{$percent}-->%</span>

in_array - 数组查找:

<!-- 检查值是否在数组中 -->
<!--{in_array array=$tags match="PHP" returnvalue="存在"}-->

4.3.4 实际应用示例

文章列表页:

<!--{iCMS:article:list loop='true' row='10' cid='1'}-->
<article class="<!--{cycle values='odd,even'}-->">
    <div class="thumb">
        <img src="<!--{$article_list.pic.0.url|thumb:300:200}-->" 
             alt="<!--{$article_list.title}-->">
    </div>
    <div class="info">
        <h3>
            <a href="<!--{$article_list.url}-->">
                <!--{$article_list.title|cut:30:'...'}-->
            </a>
        </h3>
        <div class="meta">
            <span><!--{$article_list.pubdate|date:'Y-m-d'}--></span>
            <span><!--{$article_list.hits}--> 阅读</span>
        </div>
        <p><!--{$article_list.description|cut:100:'...'|default:'暂无描述'}--></p>
    </div>
</article>
<!--{/iCMS}-->

文章详情页:

<!--{capture name="page_title"}-->
    <!--{$article.title}--> - <!--{'site_name'|lang}-->
<!--{/capture}-->

<article class="article-detail">
    <h1><!--{$article.title}--></h1>

    <div class="meta">
        <span>作者: <!--{$article.author|default:'匿名'}--></span>
        <span>发布: <!--{$article.pubdate|date:'Y-m-d H:i:s'}--></span>
        <span>阅读: <!--{$article.hits}--></span>
    </div>

    <!--{if $article.pic}-->
    <div class="featured-image">
        <img src="<!--{$article.pic.0.url|thumb:800:450}-->" 
             alt="<!--{$article.title}-->">
    </div>
    <!--{/if}-->

    <div class="content">
        <!--{$article.body|markdown}-->
    </div>

    <!--{if $article.tags}-->
    <div class="tags">
        <!--{foreach $article.tags as $tag}-->
            <a href="<!--{$tag.url}-->" class="tag">
                <!--{$tag.name}-->
            </a>
        <!--{/foreach}-->
    </div>
    <!--{/if}-->
</article>

侧边栏缓存:

<!--{cache id="sidebar_hot" time="3600"}-->
<div class="widget">
    <h3>热门文章</h3>
    <ul>
        <!--{iCMS:article:list loop='true' row='5' orderby='hits' order='desc'}-->
        <li>
            <a href="<!--{$article_list.url}-->">
                <!--{$article_list.title|cut:20:'...'}-->
            </a>
            <span class="hits"><!--{$article_list.hits}--></span>
        </li>
        <!--{/iCMS}-->
    </ul>
</div>
<!--{/cache}-->

评论列表:

<!--{foreach $comments as $comment}-->
<div class="comment <!--{cycle values='odd,even'}-->">
    <div class="author">
        <img src="<!--{$comment.avatar|thumb:50:50}-->" 
             alt="<!--{$comment.username}-->">
        <span><!--{$comment.username}--></span>
    </div>
    <div class="content">
        <!--{$comment.content|escape:'html'|nl2br}-->
    </div>
    <div class="time">
        <!--{$comment.created|date:'Y-m-d H:i:s'}-->
    </div>
</div>
<!--{/foreach}-->

4.3.5 调试技巧

输出变量内容:

<!-- 调试数组结构 -->
<!--{$article|print_r}-->

<!-- 调试变量 -->
<!--{$article|print_var}-->

<!-- JSON格式输出 -->
<!--{$data|json}-->

条件调试:

<!--{if $iCMS.debug}-->
    <div class="debug-info">
        <h3>调试信息</h3>
        <pre><!--{$article|print_r}--></pre>
    </div>
<!--{/if}-->

4.3.6 注意事项

  1. 转义字符: 调节器参数中的 | 需要用 \| 转义
  2. 链式调用: 可以连续使用多个调节器
  3. 性能考虑: 缓存块可以显著提升性能
  4. 安全处理: 用户输入必须使用 escape 转义
  5. 默认值: 使用 default 避免空值显示
  6. 调试模式: 使用 print_rprint_var 调试变量
  7. 图片优化: 使用 thumb 生成合适尺寸的缩略图

五、国际化(i18n)开发规范

5.1 语言包文件位置

5.1.1 全局语言包

中文语言包: config/lang/zh.json

{
    "site_name": "iCMS 演示站点",
    "site_description": "一个高效简洁的内容管理系统",
    "copyright": "版权所有"
}

英文语言包: config/lang/en.json

{
    "site_name": "iCMS Demo Site",
    "site_description": "An efficient and concise content management system",
    "copyright": "Copyright"
}

5.1.2 后台专用语言包

路径: app/admincp/etc/lang/zh.admincp.json

结构示例:

{
    "admincp": {
        "title": "iCMS内容管理系统",
        "slogan": "一切尽在您的掌控之中。",
        "login": {
            "welcome": "欢迎使用iCMS管理系统",
            "description": "为您提供一套高效、简洁、免费的开源解决方案"
        },
        "node": {
            "route": {
                "rule_tip": "伪静态模式时规则必需有",
                "index": {
                    "label": "首页",
                    "info": "[NODE@NAME]的首页模板"
                }
            }
        },
        "dropdown": {
            "inbox": "收件箱",
            "profile": "个人信息",
            "settings": "设置",
            "logout": "退出"
        }
    }
}

5.1.3 应用专用语言包

路径: app/[应用名]/etc/lang/zh.admincp.json

示例 (app/article/etc/lang/zh.admincp.json):

{
    "admincp": {
        "article": {
            "list": "文章列表",
            "add": "添加文章",
            "edit": "编辑文章",
            "delete": "删除文章"
        },
        "btn": {
            "add": "添加",
            "edit": "编辑",
            "delete": "删除",
            "submit": "提交",
            "cancel": "取消"
        },
        "msg": {
            "save_success": "保存成功",
            "delete_success": "删除成功"
        }
    },
    "fields": {
        "id": "ID",
        "title": "标题",
        "content": "内容",
        "status": "状态",
        "created": "创建时间"
    }
}

5.1.4 模板语言包

路径: template/[模板目录]/lang/

方式一:集中存放 (ALL.json):

{
    "zh": {
        "site_name": "iCMS 演示站点",
        "option": "其它",
        "read_more": "阅读更多"
    },
    "en": {
        "site_name": "iCMS Demo Site",
        "option": "Other",
        "read_more": "Read More"
    },
    "ja": {
        "site_name": "iCMSデモサイト",
        "option": "その他",
        "read_more": "続きを読む"
    }
}

方式二:单独存放 (en.json, zh.json):

// template/blog/lang/en.json
{
    "site_name": "iCMS Demo Site",
    "option": "Other",
    "read_more": "Read More"
}

加载优先级:

  1. 单独语言包优先(如 en.json
  2. 集中语言包备用(ALL.json

5.2 使用规范

5.2.1 命名空间规则

后台语言包:

  • admincp:模块:功能 (最多三层)
  • 示例: admincp:article:list, admincp:btn:submit

字段标签:

  • fields:字段名 (两层结构)
  • 示例: fields:title, fields:status

前台标签:

  • usercp:模块:功能 (最多三层)
  • 示例: usercp:profile:edit

5.2.2 PHP 代码中使用

// 方式1: 使用 Lang 函数
Lang('admincp:article:list');
Lang('fields:title');

// 方式2: 使用 Lang::get 方法
Lang::get('admincp:btn:submit');

// 方式3: 带默认值
Lang('admincp:custom:key', '默认值');

// 方式4: 带参数替换
Lang('admincp:msg:welcome', ['name' => $username]);

5.2.3 后台 HTML 模板中使用

<!-- 方式1: PHP 短标签 -->
<?=Lang('admincp:article:list')?>

<!-- 方式2: 完整写法 -->
<?php echo Lang('fields:title'); ?>

<!-- 方式3: 在属性中使用 -->
<input type="text" placeholder="<?=Lang('fields:title')?>" />

<!-- 方式4: 在按钮中使用 -->
<button class="btn btn-primary">
    <i class="fa fa-plus"></i> <?=Lang('admincp:btn:add')?>
</button>

5.2.4 前台模板中使用

基本用法:

<!-- 输出语言包内容 -->
<h1><!--{'site_name'|lang}--></h1>
<p><!--{'site_description'|lang}--></p>

<!-- 在链接中使用 -->
<a href="/about"><!--{'about_us'|lang}--></a>

<!-- 在按钮中使用 -->
<button><!--{'read_more'|lang}--></button>

不需要翻译的内容:

<!-- 使用 keep 过滤器保持原样 -->
<div><!--{'© 2024 iCMS'|keep}--></div>
<span><!--{'Version 8.0'|keep}--></span>

完整示例:

<!DOCTYPE html>
<html lang="<!--{$iCMS.language}-->">
<head>
    <title><!--{'site_name'|lang}--></title>
    <meta name="description" content="<!--{'site_description'|lang}-->">
</head>
<body>
    <header>
        <h1><!--{'site_name'|lang}--></h1>
        <nav>
            <a href="/"><!--{'home'|lang}--></a>
            <a href="/about"><!--{'about'|lang}--></a>
            <a href="/contact"><!--{'contact'|lang}--></a>
        </nav>
    </header>

    <main>
        <!--{iCMS:article:list loop='true' row='10'}-->
        <article>
            <h2><!--{$article_list.title}--></h2>
            <p><!--{$article_list.description}--></p>
            <a href="<!--{$article_list.url}-->">
                <!--{'read_more'|lang}-->
            </a>
        </article>
        <!--{/iCMS}-->
    </main>

    <footer>
        <p><!--{'copyright'|lang}--> <!--{'© 2024'|keep}--></p>
    </footer>
</body>
</html>

5.2.5 JavaScript 中使用

// 在 JS 中调用语言包
var message = Lang('admincp:msg:save_success');
alert(message);

// 在 AJAX 回调中使用
$.post(url, data, function(response) {
    if (response.code === 1) {
        alert(Lang('admincp:msg:save_success'));
    } else {
        alert(Lang('admincp:msg:save_failed'));
    }
});

5.3 开发最佳实践

5.3.1 语言包组织原则

  1. 分层清晰: 按模块、功能分层组织
  2. 命名规范: 使用小写字母和下划线
  3. 避免重复: 相同含义的文本使用同一个键
  4. 保持一致: 同类功能使用相同的命名模式

示例:

{
    "admincp": {
        "article": {
            "list": "文章列表",
            "add": "添加文章",
            "edit": "编辑文章"
        },
        "category": {
            "list": "分类列表",
            "add": "添加分类",
            "edit": "编辑分类"
        }
    }
}

5.3.2 多语言切换支持

模板中添加语言切换:

<div class="language-switcher">
    <a href="?lang=zh" class="<!--{if $iCMS.language=='zh'}-->active<!--{/if}-->">中文</a>
    <a href="?lang=en" class="<!--{if $iCMS.language=='en'}-->active<!--{/if}-->">English</a>
    <a href="?lang=ja" class="<!--{if $iCMS.language=='ja'}-->active<!--{/if}-->">日本語</a>
</div>

5.3.3 注意事项

  1. 键名一致性: 确保语言包中的键名与代码中使用的完全一致
  2. 默认语言: 缺失翻译时会回退到默认语言(通常为 zh
  3. 避免硬编码: 所有用户可见的文本都应使用语言包
  4. 特殊字符: 语言包中的特殊字符需要正确转义
  5. 缓存清理: 修改语言包后需清理缓存才能生效
  6. 模板过滤器: 前台模板使用 |lang 过滤器,后台使用 Lang() 函数
  7. 保持原样: 不需要翻译的内容使用 |keep 过滤器

六、数据库操作规范

6.1 查询构建器

// 基础查询
$article = ArticleModel::get($id);

// 条件查询
$list = ArticleModel::field('id,title')
    ->where('status', 1)
    ->where('cid', 10)
    ->orderBy('id', 'DESC')
    ->limit(10)
    ->select();

// 复杂条件
$where = [
    ['status', 1],
    ['cid', '>', 0],
    ['pubdate', '>=', time()],
];
$list = ArticleModel::where($where)->select();

// 插入
$id = ArticleModel::insert([
    'title' => '标题',
    'content' => '内容',
]);

// 更新
ArticleModel::update($id, [
    'title' => '新标题',
]);

// 删除
ArticleModel::delete($id);

6.2 分表操作

// 获取分表模型
$dataModel = ArticleDataModel::sharding($article_id);

// 查询
$data = $dataModel->where('article_id', $article_id)->get();

// 插入
$dataModel->insert([
    'article_id' => $article_id,
    'body' => $content,
]);

七、事件系统

7.1 模型事件

class ArticleModel extends Model
{
    protected $events = [
        'geted' => ['ArticleEvent', 'geted'],      // 查询后
        'created' => ['ArticleEvent', 'created'],  // 创建后
        'updated' => ['ArticleEvent', 'updated'],  // 更新后
        'delete' => ['ArticleEvent', 'delete'],    // 删除前
        'deleted' => ['ArticleEvent', 'deleted'],  // 删除后
        'changed' => ['ArticleEvent', 'changed'],  // 创建+更新
    ];
}

7.2 事件处理器

class ArticleEvent
{
    public static function created($response, $Builder, $event, $isMulti)
    {
        // 创建后处理
        $id = $response['id'];
        // 更新缓存、发送通知等
    }

    public static function delete($response, $Builder, $event, $isMulti)
    {
        // 删除前处理
        $id = $response['id'];
        // 清理关联数据
    }
}

八、路由配置

8.1 路由定义 (etc/route/route.json)

路由配置使用 JSON 格式,定义 URL 路径与应用控制器的映射关系。

8.1.1 基础路由格式

{
    "路径": "参数字符串"
}

8.1.2 静态路由示例

{
    "user": "app=user",
    "user/home": "app=user&do=home",
    "user/login": "app=user&do=login",
    "user/register": "app=user&do=register",
    "user/logout": "app=user&do=logout"
}

说明:

  • : URL路径 (如 user/login)
  • : 查询参数格式 (如 app=user&do=login)
  • app: 应用名称
  • do: 控制器方法名
  • s: 子方法/子页面参数

8.1.3 动态路由 (带参数)

{
    "{userid}": "app=user&do=home&userid={userid}",
    "{userid}/home": "app=user&do=home&userid={userid}",
    "{userid}/comment": "app=user&do=comment&userid={userid}",
    "{userid}/favorite/{id}": "app=user&do=favorite&userid={userid}&id={id}"
}

参数说明:

  • {userid}: 动态参数占位符
  • {id}: 其他动态参数
  • 参数会自动传递到控制器方法

8.1.4 多级路由

{
    "user/manage": "app=user&do=manage",
    "user/manage/profile": "app=user&do=manage&s=profile",
    "user/manage/message": "app=user&do=manage&s=message",
    "user/manage/order": "app=user&do=manage&s=order"
}

8.1.5 第三方登录路由

{
    "user/login/qq": "app=user&do=login&sign=qq",
    "user/login/weibo": "app=user&do=login&sign=weibo",
    "user/login/weixin": "app=user&do=login&sign=weixin",
    "user/login/github": "app=user&do=login&sign=github"
}

8.1.6 应用别名路由

{
    "UserProfile": "app=UserProfile",
    "UserPassport": "app=UserPassport",
    "UserNode/manage": "app=UserNode&do=manage"
}

8.2 节点路由配置 (node.json)

用于配置内容节点的URL规则和模板。

{
    "article": {
        "label": "文章",
        "template": "{iTPL}/article.htm",
        "rule": "/{CDIR}/{YYYY}/{MM}{DD}/{ID}{EXT}",
        "tips": "{ID},{0xID},{LINK},{HASH@ID},{HASH@0xID}"
    }
}

变量说明:

  • {iTPL}: 模板目录
  • {CDIR}: 分类目录
  • {YYYY}: 年份
  • {MM}: 月份
  • {DD}: 日期
  • {ID}: 文章ID
  • {0xID}: 16进制ID
  • {EXT}: 扩展名

8.3 路由使用示例

8.3.1 在控制器中获取路由参数

class UserApp extends AppsBase
{
    public function do_home()
    {
        // 获取路由参数
        $userid = Request::get('userid');
        $cid = Request::get('cid');

        // 业务逻辑
        $user = UserModel::get($userid);
        // ...
    }
}

8.3.2 生成路由URL

// 使用 Route 类生成URL
$url = Route::get('user', ['userid' => 123]);
// 输出: /123

$url = Route::get('user', ['userid' => 123, 'do' => 'comment']);
// 输出: /123/comment

九、开发最佳实践

9.1 代码规范

  1. 文件编码: UTF-8 without BOM
  2. 缩进: 4个空格
  3. 命名: 驼峰命名法 (类名首字母大写)
  4. 安全检查: 每个文件开头必须有 defined('iPHP') or exit('What are you doing?');

9.2 性能优化

  1. 使用缓存: 列表数据、详情数据启用缓存
  2. 分表策略: 大数据量表使用分表
  3. 字段选择: 只查询需要的字段
  4. 索引优化: 为常用查询字段添加索引

9.3 安全规范

  1. 输入验证: 所有用户输入必须验证
  2. SQL注入: 使用参数化查询
  3. XSS防护: 输出时进行HTML转义
  4. 权限检查: 后台操作检查管理员权限

9.4 调试技巧

// 开启调试模式
define('iPHP_DEBUG', true);

// 打印SQL
DB::$debug = true;

// 变量调试
var_dump($data);
print_r($array);

十、快速开发模板

10.1 创建新应用步骤

  1. 创建应用目录: app/myapp/
  2. 创建必需文件:
    • MyappModel.php
    • MyappAdmincp.php
    • MyappApp.php
    • MyappFunc.php
  3. 创建视图: views/index.html, views/add.html
  4. 配置语言包: etc/lang/zh-cn.json
  5. 配置菜单: etc/menu/admincp.php
  6. 配置路由: etc/route/route.php

10.2 完整示例代码

参考 app/article/ 目录下的完整实现。


十一、常用API参考

11.1 核心类库

类名 说明 常用方法
Model 数据模型基类 get(), insert(), update(), delete()
Request 请求处理 get(), post(), sget()
Response 响应处理 success(), error(), json()
Lang 语言处理 get(), set()
Cache 缓存处理 get(), set(), delete()
Files 文件处理 upload(), delete()
Route 路由处理 get(), url()

11.2 辅助函数

// 时间处理
time()              // 当前时间戳
str2time($str)      // 字符串转时间戳
get_date($time)     // 格式化时间

// 字符串处理
addslashes($str)    // 转义
stripslashes($str)  // 反转义
htmlspecialchars($str) // HTML转义

// 数组处理
array_column($arr, 'key')  // 提取列
array_unique($arr)         // 去重

十二、总结

iCMS8 是一个功能完善的PHP CMS框架,遵循以上规范可以快速开发出高质量的应用模块。

核心要点:

  1. 严格遵循MVC架构
  2. 使用国际化语言包
  3. 利用事件系统解耦
  4. 合理使用缓存提升性能
  5. 注重代码安全性

学习路径:

  1. 理解iPHP框架核心
  2. 研究article应用示例
  3. 实践开发简单应用
  4. 深入学习高级特性