CRMEB v8 安装目录说明
本目录是 CRMEB v8 系统的 Web 安装引导程序,通过浏览器访问 install/index.php 即可启动安装向导。安装向导是独立于 ThinkPHP 框架的纯 PHP 程序(主控逻辑全部在 index.php),按步骤 + 轮询方式分批执行安装任务,避免超时。
目录结构
install/
├── css/ # 安装向导样式文件
├── images/install/ # 安装向导图片资源
├── js/ # 前端依赖脚本
├── templates/ # 安装步骤 PHP 模板
│ ├── header.php # 公共头部(HTML head、导航)
│ ├── footer.php # 公共底部(版权信息)
│ ├── step1.php # 步骤1 - 安装许可协议
│ ├── step2.php # 步骤2 - 运行环境检测
│ ├── step3.php # 步骤3 - 数据库及管理员配置
│ ├── step4.php # 步骤4 - 安装执行过程(前端轮询驱动)
│ └── step5.php # 步骤5 - 安装完成
│
├── data/ # 按表拆分的核心初始数据 SQL
│ ├── system_config_data.sql
│ ├── system_menus_data.sql
│ └── ...
│
├── .env # 环境配置模板(含占位符,安装时替换)
├── index.php # 安装入口文件(主控逻辑)
├── crmeb_table.sql # 数据库表结构(仅 CREATE TABLE)
├── crmeb.sql.bak # 原始完整 SQL 备份(结构+数据未拆分版本),不参与安装
│
├── install.log # 安装过程日志(运行时生成,记录每条建表/写数据/插件安装结果)
└── ../install.lock # 安装完成锁文件(运行时生成于 public/ 下)
安装流程
安装向导共 5 个步骤,由 index.php 中的 $step 参数控制跳转:
| 步骤 | 模板文件 | 说明 |
|---|---|---|
| 1 | step1.php |
许可协议 — 展示用户协议,需同意后方可继续 |
| 2 | step2.php |
环境检测 — 检查 PHP 版本、扩展、目录/文件读写权限(详见下文「环境检测项」) |
| 3 | step3.php |
参数设置 — 填写数据库连接信息(MySQL + Redis)、管理员账号密码、表前缀、是否导入演示数据;提交前分别校验 MySQL 与 Redis 连通性(详见「连接校验错误码」) |
| 4 | step4.php |
安装执行 — 前端轮询接口分批执行「表结构 → 默认数据 → 插件」三个阶段(详见「安装执行三阶段」),随后写入 .env、创建管理员账户 |
| 5 | step5.php |
安装完成 — 展示安装结果,写入 .constant(安装时间与序列号),生成 install.lock 锁文件防止重复安装 |
环境检测项(步骤2)
- PHP 版本:
8.2.0≤ 版本 <8.5.0(向导展示区间为 8.2-8.4,与backend/composer.json的 php 约束一致),不满足直接终止安装。 - PHP 扩展/配置:
mysqli、curl、gd、bcmath、openssl、file_uploads、session。 - 目录可写:
backend/backup、backend/public、backend/runtime(不存在时自动创建)。 - 文件可读写:
backend/.env、backend/.version、backend/.constant。
连接校验错误码(步骤3)
MySQL 校验(前端提交 mysqldbpwd 触发):
| 返回值 | 含义 |
|---|---|
1 |
连接成功(数据库不存在但有创建权限时,会试建后删除验证) |
2002 |
地址或端口错误 |
1045 |
用户名或密码错误 |
-1 |
连接失败 |
-2 |
MySQL ≥ 5.7 且 sql_mode 含 STRICT_TRANS_TABLES / STRICT_ALL_TABLES / TRADITIONAL / ANSI,需要调整数据库配置 |
-3 |
目标数据库非空(已存在数据表,不允许覆盖安装) |
-4 |
数据库不存在且无权限创建 |
-5 |
MySQL 版本过低(须 ≥ 5.1) |
Redis 校验(前端提交 redisdbpwd 触发):实际执行 connect → auth(有密码时)→ select(指定库时)→ set 写入测试键,返回 1 成功、-1 redis 扩展缺失或对象创建失败、-3 连接或写入失败。
安装执行三阶段(步骤4)
安装接口为 index.php?step=4&install=1&phase={tables|data|plugins}&n={游标},前端逐次轮询,每次请求只执行一个最小任务单元,页面实时显示当前进度:
| 阶段 | phase 值 |
任务单元 | 结束流转 |
|---|---|---|---|
| 表结构 | tables |
执行一条 CREATE TABLE(执行前先 DROP TABLE IF EXISTS 同名表,支持覆盖安装) |
全部建表完成后返回 phase=data,游标归零 |
| 默认数据 | data |
执行一个数据文件(文件内全部 INSERT 一次执行) | 全部文件写入后执行收尾(见下),返回 phase=plugins |
| 插件安装 | plugins |
初始化 ThinkPHP 后调用 ModuleInstaller::install() 执行一个默认安装项(模块/驱动的自有表、菜单与种子数据由各自 Installer 负责) |
游标返回 n=999999 表示全部完成 |
- 三个阶段的游标
n相互独立,避免数据阶段沿用表结构的总游标。 - 数据阶段结束后由
finalizeBaseInstall()统一收尾:按需清空演示数据、替换并写入.env、重建管理员账户(truncate后插入 id=1 超管)、按安装域名更新system_config的site_url。 - 每一步执行结果都追加写入
install.log,失败时接口返回n=-2并携带失败原因,前端停止轮询并展示错误。
SQL 文件设计
采用表结构 SQL 和按表拆分的数据目录维护安装数据:
crmeb_table.sql— 核心数据库表结构(仅含CREATE TABLE语句)。data/*_data*.sql— 按表拆分的核心初始数据,一个文件对应一张表。文件名必须匹配^[a-z0-9_]+_data(?:_\d+)?\.sql$(如system_config_data.sql),文件名字典序即安装顺序;数据量特别大的表可拆分为table_data_001.sql、table_data_002.sql等文件(序号补零格式),拆分文件会按序合并为同一张表的任务单元。- 安装程序读取数据文件时仅提取其中的
INSERT INTO语句,其余内容(注释、SET 等)忽略。 crmeb.sql.bak— 原始完整 SQL 备份(结构+数据未拆分版本),仅用于对照和留档,安装程序不读取。
新增核心表与初始数据(维护指南)
核心安装 SQL 只承载系统框架自身的表与初始数据;插件/驱动的自有表、菜单与种子数据一律由各自 Installer 负责(遵循插件开发规范),不要写入本目录。
新增核心表:
- 在
crmeb_table.sql末尾追加CREATE TABLE IF NOT EXISTS \eb_表名`语句,表名一律用默认前缀eb_` 书写(安装时按用户配置前缀动态替换); - 表结构阶段每次请求执行一条 CREATE(执行前先 DROP 同名表),无需额外登记。
新增核心初始数据:
- 在
data/下新建{表名}_data.sql,一个文件只写一张表的INSERT INTO \eb_表名` ...` 语句; - 文件名字典序即执行顺序,跨表外键依赖(如先配置分组后配置项)靠命名顺序保证;
- 数据量大时可拆分为
{表名}_data_001.sql、{表名}_data_002.sql(序号补零),同一张表的拆分文件按序合并为一个任务单元一次执行; - 文件中不要写注释、
SET等非 INSERT 语句(会被忽略);不要出现生产域名(用http://demo.crmeb.com占位,安装时自动替换为实际域名,含 JSON 转义形式)。
SQL 预处理规则
所有安装 SQL 在执行前统一经过 prepareInstallSql() 处理:
| 替换项 | 说明 |
|---|---|
| 表前缀 | `eb_ → `{用户配置前缀}_(仅按反引号形式整体替换,避免误伤 smtp_host 等普通字段名) |
| 演示站域名 | http://demo.crmeb.com → 实际安装域名 |
| JSON 内层域名 | http:\/\/demo.crmeb.com(JSON 转义形式)→ 转义形式的实际域名,保证 eb_diy、eb_theme 等 JSON 数据安装后同样指向本站 |
实际域名(scheme + host)按以下优先级获取,适配反向代理部署:
- 反向代理头
X-Forwarded-Proto/X-Forwarded-Host; HTTPS/HTTP_HOST;SERVER_NAME(非标准端口时自动拼接端口号)。
.env 配置模板
.env 文件包含占位符,安装过程中由安装程序自动替换为用户填写的实际值后写入 backend/.env:
| 占位符 | 说明 |
|---|---|
#APP_KEY# |
应用密钥(自动生成,格式 app_key_{uniqid}) |
#DB_HOST# / #DB_PORT# / #DB_USER# / #DB_PWD# / #DB_NAME# / #DB_PREFIX# |
MySQL 数据库连接信息 |
#CACHE_TYPE# / #CACHE_PREFIX# / #CACHE_TAG_PREFIX# |
缓存配置(file 或 redis),前缀含随机值用于多实例隔离 |
#RB_HOST# / #RB_PORT# / #RB_PWD# / #RB_SELECT# |
Redis 连接信息 |
#QUEUE_NAME# |
队列名称(自动生成唯一值) |
演示数据控制
步骤4可选择是否导入演示数据;不导入演示数据时,默认数据阶段收尾(finalizeBaseInstall())会对库中全部数据表执行 truncate,仅保留以下白名单表:
- 清理发生在插件安装之前(
tables → data → 清理 → plugins),因此插件/驱动安装的自有表与种子数据写入在清理之后,天然不受影响。 - 白名单按
SHOW TABLES实际存在的表过滤,仅对实际存在的表执行清理。
白名单($baseTables,共 37 项,按默认前缀 eb_ 列出,实际按用户配置前缀匹配):
| 分类 | 表名 |
|---|---|
| 系统配置 | system_config、system_config_tab、system_group、system_group_data、system_event_data |
| 菜单路由与权限 | system_menus、system_route、system_route_cate、system_admin、system_user_level |
| 系统任务与工单 | system_crontab、system_ticket、system_city |
| 内容与页面 | diy、page_categroy、page_link、agreement、cache |
| 物流配送 | express、express_company、express_template、shipping_templates、shipping_templates_region |
| 多语言 | lang_code、lang_country、lang_type |
| 会员与通知 | member_right、member_ship、agent_level、notice_config、notice_channel |
| 支付与驱动 | pay_channel、pay_channel_platform、driver、printer_channel、out_interface |
| 模块安装 | module_install_log |
运行时生成与读取的文件
| 文件 | 位置 | 说明 |
|---|---|---|
install.log |
install/ 目录内 |
每条建表、写数据、插件安装的结果日志(含时间戳与失败原因),排障首选 |
.env |
backend/.env |
收尾阶段由模板替换占位符后写入 |
.constant |
backend/.constant |
步骤5写入 INSTALL_DATE(安装时间戳)与 SERIALNUMBER(随机序列号) |
install.lock |
public/install.lock |
安装完成锁文件 |
.version |
backend/.version |
非生成文件;步骤5读取其中 version / platform 用于安装完成页展示 |
关键逻辑说明
- 防重复安装:入口处检测
public/install.lock,存在即阻止进入向导;如需重装,需手动删除public/install.lock。 - 环境变量优先:数据库和 Redis 连接信息默认值优先从容器的
MYSQL_HOST_IP、MYSQL_PORT、MYSQL_USER、MYSQL_PASSWORD、MYSQL_DATABASE、REDIS_HOST_IP等环境变量获取,适用于 Docker 部署场景;表单填写值仍以步骤3提交为准。 - 表前缀替换:SQL 文件默认使用
eb_前缀,安装时按反引号整体形式动态替换为用户配置前缀;覆盖安装时DROP TABLE按实际前缀执行。 - 数据库不存在时自动创建:按
utf8mb4/utf8mb4_0900_ai_ci字符集执行CREATE DATABASE IF NOT EXISTS。 - 管理员账户:收尾阶段清空
system_admin后写入 id=1 的超级管理员(账号为步骤3填写,密码经PASSWORD_BCRYPT加密,角色roles=1)。 - 站点域名写入:收尾阶段将安装访问域名以 JSON 字符串形式更新到
system_config的site_url(与系统配置读取侧json_decode约定一致)。 - 最低要求:PHP 8.2-8.4(不含 8.5+),MySQL ≥ 5.1(5.7+ 需关闭严格 sql_mode),Redis 扩展(选择 redis 缓存时必需)。