搜索

📄 文章 📚 合集
热门搜索
🐘 PHP ⚡ Laravel 🎨 Vue.js ⚛️ React 📦 Yii 📘 JavaScript 🗄️ MySQL 🐳 Docker
返回合集

[板块x:修复bug] - 05- 优化一键安装脚本健壮性

代码示例
# 优化一键安装脚本,提升部署健壮性

## 1。背景

在好站站企业建站引擎的实际部署过程中,发现一键安装脚本存在以下潜在问题:

| 问题 | 描述 |
|------|------|
| APP_URL 可能为空 | 当 `$_SERVER['HTTP_HOST']` 不存在时(如 CLI 环境),生成的 `.env` 文件中 `APP_URL` 为空 |
| 重复安装邮箱冲突 | 重复执行安装时,管理员邮箱违反唯一约束,导致安装失败 |
| 外键约束错误 | 建表时直接添加外键,但 `sites` 表还没数据,导致 `pages` 表创建失败 |
| site_id 写死 | `site_id` 写死为 1,但 `sites` 表可能为空或 ID 不是 1 |

---

## 2。修改内容

### 2.1 优化 APP_URL 获取

**文件位置**:`public/install.php`

**修改前**:

```php
$envContent .= 'APP_URL=http://' . $_SERVER['HTTP_HOST'] . "\n";
```

**修改后**:

```php
$appUrl = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
$envContent .= 'APP_URL=http://' . $appUrl . "\n";
```

**原因**:使用空合并运算符,当 `HTTP_HOST` 不存在时,依次尝试 `SERVER_NAME`,最后使用 `localhost` 作为默认值。

### 2.2 调整建表顺序,解决外键约束

**修改前**:创建 `pages` 表时直接添加外键约束,但 `sites` 表可能还没有数据。

**修改后**:先创建所有表(不加外键),插入数据后,再单独添加外键约束。

```php
// 1. 先创建 sites 表并插入数据
$pdo->exec("CREATE TABLE IF NOT EXISTS `sites` (...)");
// 插入站点数据...

// 2. 创建其他表(不加外键)
$pdo->exec("CREATE TABLE IF NOT EXISTS `pages` (...)");
$pdo->exec("CREATE TABLE IF NOT EXISTS `page_components` (...)");

// 3. 数据插入完成后,再添加外键
$pdo->exec("ALTER TABLE `pages` ADD CONSTRAINT `pages_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE");
```

**原因**:避免建表时因外键依赖导致失败。

### 2.3 动态获取站点 ID

**修改前**:

```php
$siteId = 1;
```

**修改后**:

```php
$stmt = $pdo->query("SELECT COUNT(*) FROM sites");
if ($stmt->fetchColumn() == 0) {
    $pdo->exec("INSERT INTO sites (...) VALUES (...)");
    $siteId = $pdo->lastInsertId();
} else {
    $stmt = $pdo->query("SELECT id FROM sites LIMIT 1");
    $siteId = $stmt->fetchColumn();
}
```

**原因**:动态获取或创建站点记录,确保 `site_id` 正确。

### 2.4 管理员邮箱去重处理

**修改前**:


$stmt = $pdo->prepare("INSERT INTO users (name, email, password, ...) VALUES (?, ?, ?, ...)");
$stmt->execute([$admin_name, $admin_email, $hashed]);
```

**修改后**:


$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
$stmt->execute([$admin_email]);
$emailExists = $stmt->fetchColumn();

if ($emailExists == 0) {
    // 不存在,插入新用户
    $stmt = $pdo->prepare("INSERT INTO users (name, email, password, ...) VALUES (?, ?, ?, ...)");
    $stmt->execute([$admin_name, $admin_email, $hashed]);
} else {
    // 已存在,更新密码
    $stmt = $pdo->prepare("UPDATE users SET name = ?, password = ?, updated_at = NOW() WHERE email = ?");
    $stmt->execute([$admin_name, $hashed, $admin_email]);
}
```

**原因**:先检查邮箱是否存在,存在则更新密码,不存在则创建新用户,避免重复安装时的唯一约束冲突。

---

## 3。修改文件清单

| 文件 | 操作 | 说明 |
|------|------|------|
| `public/install.php` | 修改 | 优化建表顺序、APP_URL 获取、管理员创建、站点 ID 获取 |

---

## 4。验证结果

| 验证项 | 预期结果 | 实际结果 |
|--------|---------|---------|
| APP_URL 生成 | 始终有值,不为空 | ✅ |
| 建表顺序 | 先 sites 后 pages,外键最后添加 | ✅ |
| 站点 ID 获取 | 动态获取,不写死 | ✅ |
| 重复安装 | 不会因邮箱冲突失败 | ✅ |
| 全新安装 | 所有表正常创建 | ✅ |

---

## 5。提交记录

```bash
git add public/install.php
git commit -m "fix(install): 优化一键安装脚本健壮性

- 优化 APP_URL 获取,增加备选值
- 调整建表顺序,先创建 sites 表,外键最后添加
- 动态获取站点 ID,避免外键约束错误
- 管理员邮箱去重处理,避免重复安装冲突"

git push origin main
```


🧸 adorable code

专注 PHP、JavaScript、Laravel、Vue.js、React、Yii 全栈开发。记录技术探索过程中的灵感与经验,分享工程实践洞见。

hello@adorablecode.com