Files
TripLog/src/helpers.php
T

83 lines
2.0 KiB
PHP
Raw Normal View History

<?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;
}