'已经装好了', 'message' => '「家书」已经安装过。如果要重新安装,请先清空数据库里的 families / persons / accounts / settings 四张表。', ]); exit; } $dbName = $GLOBALS['config']['db']['name']; if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') { csrf_check(); $familyName = trim((string)($_POST['family_name'] ?? '')); $motto = trim((string)($_POST['motto'] ?? '')); $name = trim((string)($_POST['name'] ?? '')); $phone = trim((string)($_POST['phone'] ?? '')); $password = (string)($_POST['password'] ?? ''); $errors = []; if ($familyName === '') { $errors['_'] = '家庭名称不能为空'; } if ($name === '') { $errors['name'] = '请填写你的姓名'; } if (!preg_match('/^\+?[0-9\-]{6,20}$/', $phone)) { $errors['phone'] = '手机号格式看起来不对'; } $pwErr = Account::validatePassword($password); if ($pwErr) { $errors['password'] = implode(';', $pwErr); } if (!$errors) { try { // ensure() 而不是逐条 exec(statements()):它还会补齐后加的列与枚举值, // 所以老库重新跑一次就能自动升级,不必手工改表。 Schema::ensure(); $familyId = Family::create($familyName, $motto); // 装完就把结构版本盖上:不盖的话,第一次进首页发现"版本对不上", // 会再跑一次 ensure()(幂等,不出错,但白跑一遍 ALTER 查询)。 \App\Setting::set($familyId, 'schema_version', Schema::VERSION); $personId = Person::create($familyId, [ 'name' => $name, 'gender' => '', 'avatar' => '', 'phone' => $phone, 'id_card' => '', 'email' => '', 'address' => '', 'note' => '', 'slogan' => '', 'sort_order'=> 1, 'kind' => 'member', ]); Account::create($personId, $password, 'admin'); // 装完就删掉自己 —— 避免把安装入口长期暴露在公网 @unlink(__FILE__); header('Location: index.php?r=auth/login'); exit; } catch (\Throwable $ex) { $errors['_'] = '安装失败:' . $ex->getMessage(); } } set_old($_POST); View::renderBare('install', [ 'title' => '安装家书', 'dbName' => $dbName, 'errors' => $errors, ]); exit; } clear_old(); View::renderBare('install', [ 'title' => '安装家书', 'dbName' => $dbName, 'errors' => [], ]);