83 lines
2.0 KiB
PHP
83 lines
2.0 KiB
PHP
<?php
|
|||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
function e($value): string
|
||
|
|
{
|
||
|
|
return htmlspecialchars((string)($value ?? ''), ENT_QUOTES, 'UTF-8');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 读取 config.php(每个请求只读一次)
|
||
|
|
* 页面里的第三方 Key 一律从这里取,避免同一个值散落在多个文件里
|
||
|
|
*/
|
||
|
|
function app_config(): array
|
||
|
|
{
|
||
|
|
static $config = null;
|
||
|
|
if ($config === null) {
|
||
|
|
$config = require dirname(__DIR__) . '/config.php';
|
||
|
|
}
|
||
|
|
return $config;
|
||
|
|
}
|
||
|
|
|
||
|
|
function url(string $route, array $params = []): string
|
||
|
|
{
|
||
|
|
$params = array_merge(['r' => $route], $params);
|
||
|
|
return '/index.php?' . http_build_query($params);
|
||
|
|
}
|
||
|
|
|
||
|
|
function redirect(string $route, array $params = [], string $anchor = ''): void
|
||
|
|
{
|
||
|
|
$location = url($route, $params);
|
||
|
|
if ($anchor !== '') {
|
||
|
|
$location .= '#' . ltrim($anchor, '#');
|
||
|
|
}
|
||
|
|
header('Location: ' . $location);
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
function view(string $template, array $data = []): void
|
||
|
|
{
|
||
|
|
extract($data, EXTR_SKIP);
|
||
|
|
$basePath = dirname(__DIR__);
|
||
|
|
$content = $basePath . '/templates/' . $template . '.php';
|
||
|
|
if (!file_exists($content)) {
|
||
|
|
throw new \RuntimeException("模板不存在: $template");
|
||
|
|
}
|
||
|
|
require $basePath . '/templates/layout.php';
|
||
|
|
}
|
||
|
|
|
||
|
|
function flash(string $key, ?string $value = null): ?string
|
||
|
|
{
|
||
|
|
if ($value !== null) {
|
||
|
|
$_SESSION['_flash'][$key] = $value;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
$v = $_SESSION['_flash'][$key] ?? null;
|
||
|
|
unset($_SESSION['_flash'][$key]);
|
||
|
|
return $v;
|
||
|
|
}
|
||
|
|
|
||
|
|
function csrf_token(): string
|
||
|
|
{
|
||
|
|
if (empty($_SESSION['_csrf'])) {
|
||
|
|
$_SESSION['_csrf'] = bin2hex(random_bytes(16));
|
||
|
|
}
|
||
|
|
return $_SESSION['_csrf'];
|
||
|
|
}
|
||
|
|
|
||
|
|
function csrf_check(): void
|
||
|
|
{
|
||
|
|
$token = $_POST['_csrf'] ?? '';
|
||
|
|
if (!hash_equals($_SESSION['_csrf'] ?? '', $token)) {
|
||
|
|
http_response_code(419);
|
||
|
|
exit('CSRF token 校验失败');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function json_decode_field($json, $default = [])
|
||
|
|
{
|
||
|
|
if (empty($json)) return $default;
|
||
|
|
if (is_array($json)) return $json;
|
||
|
|
$decoded = json_decode($json, true);
|
||
|
|
return $decoded ?? $default;
|
||
|
|
}
|