辅助函数
DuxLite 提供了丰富的辅助函数集合,覆盖路径处理、时间操作、字符串处理、数学运算、加密解密、网络工具等常用功能。这些函数都是全局可用的,无需导入即可使用。
设计理念
DuxLite 辅助函数采用简单、实用、高效的工具函数集合设计:
- 全局可用:所有函数都在全局作用域中,无需导入
- 类型安全:支持现代PHP类型声明,提供更好的IDE支持
- 防冲突:使用
function_exists()
检查,避免与其他库冲突 - 性能优化:内置缓存和优化机制
- 国际化支持:错误信息和用户界面支持多语言
函数分类
- 路径处理函数:base_path、app_path、data_path等
- 时间处理函数:now() 函数
- 字符串处理函数:str_hidden、human_filesize等
- 数学运算函数:bc_format、bc_math、bc_comp高精度运算
- 加密解密函数:encryption、decryption数据安全
- 网络和工具函数:get_ip、is_service等
- URL 生成函数:url() 路由 URL 生成
- 调试和开发函数:dd() 变量调试
- 国际化翻译函数:__() 多语言翻译
路径处理函数
基础路径函数
php
// 项目根目录路径
$basePath = base_path(); // /path/to/project
$configFile = base_path('config/use.toml'); // /path/to/project/config/use.toml
// 应用代码目录路径
$appPath = app_path(); // /path/to/project/app
$controller = app_path('Web/Controllers/UserController.php');
// 数据存储目录路径
$dataPath = data_path(); // /path/to/project/data
$logFile = data_path('logs/app.log'); // /path/to/project/data/logs/app.log
// 公共访问目录路径
$publicPath = public_path(); // /path/to/project/public
$uploadFile = public_path('uploads/avatar.jpg');
// 配置文件目录路径
$configPath = config_path(); // /path/to/project/config
$dbConfig = config_path('database.toml');
系统路径函数
php
// 通用路径处理函数(底层实现)
$fullPath = sys_path('/base/path', 'sub/path'); // /base/path/sub/path
$normalizedPath = sys_path('C:\\Windows\\Path', 'file.txt'); // C:/Windows/Path/file.txt
特性:
- 自动处理不同操作系统的路径分隔符
- 规范化路径格式(统一使用
/
) - 移除多余的分隔符
实际应用示例
php
// 配置文件加载
$configFile = config_path('app.toml');
if (file_exists($configFile)) {
$config = parse_toml_file($configFile);
}
// 日志文件写入
$logDir = data_path('logs');
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
file_put_contents(data_path('logs/error.log'), $errorMessage, FILE_APPEND);
// 上传文件保存
$uploadDir = public_path('uploads/' . date('Y/m'));
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$uploadPath = public_path('uploads/' . date('Y/m') . '/' . $filename);
// 模板文件包含
$templateFile = app_path('Views/email.latte');
$template = file_get_contents($templateFile);
时间处理函数
now() 函数
基于 Carbon 库的时间处理函数:
php
use Carbon\Carbon;
// 基础用法
$currentTime = now(); // Carbon 实例
$timestamp = now()->timestamp; // Unix 时间戳
$formatted = now()->format('Y-m-d H:i:s'); // 格式化时间
// 时区处理
$utcTime = now('UTC'); // UTC 时间
$localTime = now('Asia/Shanghai'); // 指定时区
$offsetTime = now('+08:00'); // 时区偏移
// 在模型中使用
class Post extends Model
{
protected $fillable = ['title', 'content', 'published_at'];
public static function boot()
{
parent::boot();
static::creating(function ($post) {
$post->published_at = now(); // 设置发布时间
});
}
}
// 在服务类中使用
class OrderService
{
public function createOrder(array $data): Order
{
return Order::create([
'order_no' => $this->generateOrderNo(),
'amount' => $data['amount'],
'created_at' => now(),
'expires_at' => now()->addHours(2), // 2小时后过期
]);
}
}
// 时间比较和计算
$startTime = now();
// ... 执行一些操作
$endTime = now();
$duration = $endTime->diffInSeconds($startTime);
// 常用时间操作
$tomorrow = now()->addDay();
$nextWeek = now()->addWeek();
$lastMonth = now()->subMonth();
$weekStart = now()->startOfWeek();
$monthEnd = now()->endOfMonth();
字符串处理函数
str_hidden() - 字符串隐藏
用于隐藏敏感信息,如手机号、邮箱、身份证等:
php
// 基础用法
$phone = '13888888888';
$hiddenPhone = str_hidden($phone, 50); // 138****8888
// 自定义隐藏字符
$email = 'user@example.com';
$hiddenEmail = str_hidden($email, 60, '#'); // us####ample.com
// 邮箱特殊处理
$email = 'user@example.com';
$hiddenEmail = str_hidden($email, 50, '*', '@'); // us**@example.com
// 实际应用示例
class UserService
{
public function getUserProfile(int $userId): array
{
$user = User::find($userId);
return [
'id' => $user->id,
'username' => $user->username,
// 隐藏手机号中间4位
'phone' => str_hidden($user->phone, 40),
// 隐藏邮箱用户名部分
'email' => str_hidden($user->email, 50, '*', '@'),
// 隐藏身份证号中间部分
'id_card' => str_hidden($user->id_card, 70),
];
}
}
// 不同隐藏程度
$text = 'sensitive-data';
$light = str_hidden($text, 20); // 隐藏20%:sensiti##-data
$medium = str_hidden($text, 50); // 隐藏50%:sen######data
$heavy = str_hidden($text, 80); // 隐藏80%:s###########a
human_filesize() - 文件大小格式化
将字节数转换为人类可读的文件大小:
php
// 基础用法
echo human_filesize(1024); // 1.00 kB
echo human_filesize(1048576); // 1.00 MB
echo human_filesize(1073741824); // 1.00 GB
// 自定义小数位数
echo human_filesize(1234567, 1); // 1.2 MB
echo human_filesize(1234567, 3); // 1.177 MB
// 实际应用示例
class FileController
{
public function uploadFile(ServerRequestInterface $request): ResponseInterface
{
$uploadedFile = $request->getUploadedFiles()['file'];
$fileSize = $uploadedFile->getSize();
// 检查文件大小
if ($fileSize > 10 * 1024 * 1024) { // 10MB
throw new ExceptionBusiness(
'文件大小不能超过 ' . human_filesize(10 * 1024 * 1024)
);
}
return send($response, '上传成功', [
'filename' => $uploadedFile->getClientFilename(),
'size' => human_filesize($fileSize),
'size_bytes' => $fileSize
]);
}
public function getFileList(): array
{
$files = scandir(public_path('uploads'));
$result = [];
foreach ($files as $file) {
if (in_array($file, ['.', '..'])) continue;
$filePath = public_path('uploads/' . $file);
$result[] = [
'name' => $file,
'size' => human_filesize(filesize($filePath)),
'modified' => date('Y-m-d H:i:s', filemtime($filePath))
];
}
return $result;
}
}
数学运算函数
DuxLite 提供了基于 BCMath 的高精度数学运算函数,避免浮点数精度问题:
bc_format() - 数字格式化
php
// 基础用法
echo bc_format(123.456); // 123.46
echo bc_format(123.456, 1); // 123.5
echo bc_format(123.456, 3); // 123.456
// 金融计算中的应用
class OrderService
{
public function calculateTotal(array $items): string
{
$total = 0;
foreach ($items as $item) {
$subtotal = $item['price'] * $item['quantity'];
$total += $subtotal;
}
return bc_format($total, 2); // 保证金额精度
}
}
bc_math() - 高精度运算
php
// 基础运算
$sum = bc_math(10.15, '+', 20.25); // 30.40
$diff = bc_math(100.50, '-', 20.15); // 80.35
$product = bc_math(10.5, '*', 2.5); // 26.25
$quotient = bc_math(100, '/', 3); // 33.33
$remainder = bc_math(100, '%', 7); // 2
// 自定义精度
$result = bc_math(10, '/', 3, 4); // 3.3333
// 实际应用:购物车计算
class CartService
{
public function calculateCart(array $cartItems): array
{
$subtotal = '0.00';
$taxRate = '0.08'; // 8% 税率
foreach ($cartItems as $item) {
$itemTotal = bc_math($item['price'], '*', $item['quantity'], 2);
$subtotal = bc_math($subtotal, '+', $itemTotal, 2);
}
$tax = bc_math($subtotal, '*', $taxRate, 2);
$total = bc_math($subtotal, '+', $tax, 2);
return [
'subtotal' => $subtotal,
'tax' => $tax,
'total' => $total
];
}
}
// 金融利息计算
class LoanCalculator
{
public function calculateInterest(string $principal, string $rate, int $months): string
{
// 月利率
$monthlyRate = bc_math($rate, '/', '12', 6);
// 复利计算:P * (1 + r)^n
$amount = $principal;
for ($i = 0; $i < $months; $i++) {
$amount = bc_math($amount, '*', bc_math('1', '+', $monthlyRate, 6), 2);
}
return bc_math($amount, '-', $principal, 2); // 利息 = 总额 - 本金
}
}
bc_comp() - 数值比较
php
// 基础比较
$result = bc_comp('10.50', '10.25'); // 1 (大于)
$result = bc_comp('10.25', '10.50'); // -1 (小于)
$result = bc_comp('10.50', '10.50'); // 0 (等于)
// 自定义精度比较
$result = bc_comp('10.123', '10.124', 2); // 0 (精度为2时相等)
$result = bc_comp('10.123', '10.124', 3); // -1 (精度为3时小于)
// 实际应用:价格比较
class ProductService
{
public function findCheaperProducts(string $maxPrice): array
{
$products = Product::all();
$cheaperProducts = [];
foreach ($products as $product) {
if (bc_comp($product->price, $maxPrice, 2) <= 0) {
$cheaperProducts[] = $product;
}
}
return $cheaperProducts;
}
public function validatePriceRange(string $price, string $min, string $max): bool
{
return bc_comp($price, $min, 2) >= 0 && bc_comp($price, $max, 2) <= 0;
}
}
加密解密函数
encryption() / decryption() - 数据加密解密
基于 OpenSSL 的对称加密,用于敏感数据保护:
php
// 基础用法(使用应用密钥)
$encrypted = encryption('sensitive data');
$decrypted = decryption($encrypted);
// 自定义密钥
$key = 'your-32-char-encryption-key-here';
$encrypted = encryption('sensitive data', $key);
$decrypted = decryption($encrypted, $key);
// 自定义IV和加密方法
$iv = random_bytes(16);
$encrypted = encryption('data', $key, $iv, 'AES-256-CBC');
$decrypted = decryption($encrypted, $key, $iv, 'AES-256-CBC');
// 实际应用:用户敏感信息加密
class UserService
{
public function saveUserProfile(array $data): User
{
// 加密敏感信息
if (isset($data['id_card'])) {
$data['id_card'] = encryption($data['id_card']);
}
if (isset($data['bank_account'])) {
$data['bank_account'] = encryption($data['bank_account']);
}
return User::create($data);
}
public function getUserProfile(int $userId): array
{
$user = User::find($userId);
return [
'id' => $user->id,
'username' => $user->username,
// 解密敏感信息
'id_card' => $user->id_card ? decryption($user->id_card) : null,
'bank_account' => $user->bank_account ? decryption($user->bank_account) : null,
];
}
}
// 配置信息加密存储
class ConfigService
{
public function saveApiKey(string $service, string $apiKey): void
{
Config::updateOrCreate(
['key' => "api_key_{$service}"],
['value' => encryption($apiKey)]
);
}
public function getApiKey(string $service): ?string
{
$config = Config::where('key', "api_key_{$service}")->first();
return $config ? decryption($config->value) : null;
}
}
// 错误处理
try {
$encrypted = encryption('data');
$decrypted = decryption($encrypted);
} catch (ExceptionBusiness $e) {
// 加密/解密失败处理
App::log()->error('加密操作失败', ['error' => $e->getMessage()]);
}
网络和工具函数
get_ip() - IP地址获取
智能获取用户真实IP地址,支持代理和负载均衡:
php
// 基础用法
$userIp = get_ip();
// 获取IP的优先级:
// 1. HTTP_CLIENT_IP(客户端IP)
// 2. HTTP_X_REAL_IP(Nginx真实IP)
// 3. HTTP_X_FORWARDED_FOR(转发IP,取第一个)
// 4. REMOTE_ADDR(远程地址)
// 5. 默认返回 '0.0.0.0'
// 实际应用:用户访问记录
class AccessLogService
{
public function logAccess(ServerRequestInterface $request): void
{
AccessLog::create([
'ip' => get_ip(),
'user_agent' => $request->getHeaderLine('User-Agent'),
'url' => $request->getUri()->getPath(),
'method' => $request->getMethod(),
'created_at' => now()
]);
}
}
// 安全限制:IP黑名单
class SecurityService
{
private array $blacklistIps = ['192.168.1.100', '10.0.0.50'];
public function checkIpBlacklist(): bool
{
$currentIp = get_ip();
return in_array($currentIp, $this->blacklistIps);
}
}
// 地域限制
class GeoService
{
public function isAllowedRegion(): bool
{
$ip = get_ip();
$geoInfo = $this->getGeoInfo($ip);
return in_array($geoInfo['country'], ['CN', 'US', 'UK']);
}
}
is_service() - 服务检测
检查是否在服务模式下运行(如Swoole、ReactPHP等):
php
// 基础用法
if (is_service()) {
// 服务模式下的特殊处理
echo "运行在服务模式下\n";
} else {
// 传统CGI/FPM模式
echo "运行在传统模式下\n";
}
// 实际应用:缓存策略
class CacheService
{
public function get(string $key)
{
if (is_service()) {
// 服务模式:使用内存缓存
return $this->getFromMemory($key);
} else {
// 传统模式:使用文件缓存
return $this->getFromFile($key);
}
}
}
// 应用初始化
class AppBootstrap
{
public function boot(): void
{
if (is_service()) {
// 服务模式:预加载配置
$this->preloadConfigs();
$this->initializeConnections();
} else {
// 传统模式:按需加载
$this->lazyLoadConfigs();
}
}
}
调试和开发函数
dd() - 变量调试
基于 Symfony VarDumper 的调试函数:
php
// 基础用法
$data = ['name' => 'DuxLite', 'version' => '2.0'];
dd($data); // 输出变量内容并终止程序
// 多变量调试
$user = User::find(1);
$orders = $user->orders;
dd($user, $orders); // 同时输出多个变量
// 条件调试
if ($debug) {
dd($queryResult);
}
// 实际应用:调试API响应
class ApiController
{
public function getUserData(int $userId): array
{
$user = User::with(['profile', 'orders'])->find($userId);
// 开发环境下调试
if (App::$debug) {
dd($user->toArray());
}
return $user->toArray();
}
}
// 调试复杂查询
class ReportService
{
public function generateReport(): array
{
$query = User::query()
->with(['orders' => function($q) {
$q->where('status', 'completed');
}])
->withCount('orders')
->having('orders_count', '>', 10);
// 调试SQL查询
if (App::$debug) {
dd($query->toSql(), $query->getBindings());
}
return $query->get()->toArray();
}
}
URL 生成函数
url() - 路由 URL 生成
基于路由名称生成完整的 URL 地址:
php
// 基础用法
$userListUrl = url('admin.users.list', []); // /admin/users
$userDetailUrl = url('admin.users.show', ['id' => 123]); // /admin/users/123
// 带参数的复杂路由
$resetPasswordUrl = url('admin.users.resetPassword', ['id' => 456]); // /admin/users/reset-password/456
// 实际应用示例
class UserController extends Resources
{
public function transform(object $item): array
{
return [
'id' => $item->id,
'username' => $item->username,
'email' => $item->email,
// 生成相关链接
'links' => [
'self' => url('admin.users.show', ['id' => $item->id]),
'edit' => url('admin.users.edit', ['id' => $item->id]),
'delete' => url('admin.users.delete', ['id' => $item->id]),
'reset_password' => url('admin.users.resetPassword', ['id' => $item->id])
]
];
}
}
// 在邮件模板中使用
class EmailService
{
public function sendWelcomeEmail(User $user): void
{
$activationUrl = url('user.activate', ['token' => $user->activation_token]);
$loginUrl = url('user.login', []);
$emailData = [
'user' => $user,
'activation_url' => $activationUrl,
'login_url' => $loginUrl
];
Mail::send('emails.welcome', $emailData, $user->email);
}
}
// API 响应中生成资源链接
class ApiProductController extends Resources
{
public function transform(object $item): array
{
return [
'id' => $item->id,
'name' => $item->name,
'price' => $item->price,
'category' => [
'id' => $item->category_id,
'name' => $item->category->name,
'url' => url('api.categories.show', ['id' => $item->category_id])
],
'images' => array_map(function($image) {
return [
'url' => $image['url'],
'thumbnail' => url('api.images.thumbnail', ['id' => $image['id']])
];
}, $item->images ?? []),
'_links' => [
'self' => url('api.products.show', ['id' => $item->id]),
'category' => url('api.categories.show', ['id' => $item->category_id]),
'reviews' => url('api.products.reviews', ['id' => $item->id])
]
];
}
}
// 分页链接生成
class PaginationHelper
{
public static function generatePaginationLinks(string $routeName, array $params, int $currentPage, int $totalPages): array
{
$links = [];
// 上一页
if ($currentPage > 1) {
$prevParams = array_merge($params, ['page' => $currentPage - 1]);
$links['prev'] = url($routeName, $prevParams);
}
// 下一页
if ($currentPage < $totalPages) {
$nextParams = array_merge($params, ['page' => $currentPage + 1]);
$links['next'] = url($routeName, $nextParams);
}
// 首页和末页
$links['first'] = url($routeName, array_merge($params, ['page' => 1]));
$links['last'] = url($routeName, array_merge($params, ['page' => $totalPages]));
return $links;
}
}
// 表单action URL生成
class FormBuilder
{
public function generateForm(string $action, array $data = []): string
{
$actionUrl = match($action) {
'create' => url('admin.users.create', []),
'edit' => url('admin.users.edit', ['id' => $data['id']]),
'delete' => url('admin.users.delete', ['id' => $data['id']]),
default => throw new InvalidArgumentException("Unknown action: {$action}")
};
return sprintf('<form action="%s" method="POST">...</form>', $actionUrl);
}
}
特性:
- 基于 SlimPHP 路由解析器生成 URL
- 自动处理路由参数替换
- 支持嵌套路由名称(如
admin.users.show
) - 生成的 URL 相对于应用根目录
- 参数类型安全,自动转换为字符串
注意事项:
- 路由名称必须是已注册的有效路由
- 参数数组的键必须与路由中定义的参数名匹配
- 缺少必需参数会抛出异常
- 生成的是相对路径,需要配合域名使用时要额外处理
国际化翻译函数
__() - 多语言翻译
支持参数化翻译和多域翻译:
php
// 基础用法
echo __('welcome.message'); // 从当前语言包获取翻译
// 带参数的翻译
echo __('user.welcome', ['name' => 'John']); // Hello, John!
// 指定翻译域
echo __('errors.not_found', [], 'admin'); // 从admin域获取翻译
// 参数和域同时使用
echo __('order.total', ['amount' => 100], 'shop');
// 语言包文件示例 (common.zh-CN.toml)
[welcome]
message = "欢迎使用DuxLite"
[user]
welcome = "你好,%name%!"
profile = "用户资料"
[errors]
not_found = "页面不存在"
access_denied = "访问被拒绝"
// 在控制器中使用
class UserController
{
public function create(): ResponseInterface
{
$data = [
'title' => __('user.create_title'),
'description' => __('user.create_desc'),
'form_fields' => [
'username' => __('user.username'),
'email' => __('user.email'),
'password' => __('user.password')
]
];
return send($response, __('common.success'), $data);
}
}
// 在验证规则中使用
class UserValidator
{
public static function rules(): array
{
return [
'username' => [
['required', __('validation.required', ['field' => __('user.username')])],
['lengthMin', 3, __('validation.min_length', ['field' => __('user.username'), 'min' => 3])]
],
'email' => [
['required', __('validation.required', ['field' => __('user.email')])],
['email', __('validation.email', ['field' => __('user.email')])]
]
];
}
}
// 在模板中使用(Latte模板)
// {__('welcome.message')}
// {__('user.welcome', ['name' => $user->name])}
// {__('errors.not_found', [], 'admin')}
// 动态语言切换
class LanguageController
{
public function switchLanguage(string $locale): ResponseInterface
{
// 设置新语言
App::di()->set('lang', $locale);
return send($response, __('language.switched'), [
'current_language' => $locale,
'message' => __('welcome.message') // 返回新语言的欢迎信息
]);
}
}
最佳实践
1. 路径处理
php
// ✅ 正确:使用路径函数
$configFile = config_path('app.toml');
$logDir = data_path('logs');
$uploadPath = public_path('uploads/' . $filename);
// ❌ 避免:硬编码路径
$configFile = '/var/www/project/config/app.toml';
$logDir = '../data/logs';
2. 数学运算
php
// ✅ 正确:金融计算使用BC函数
$total = bc_math($price, '*', $quantity, 2);
$tax = bc_math($total, '*', '0.08', 2);
// ❌ 避免:浮点数直接运算(精度问题)
$total = $price * $quantity; // 可能有精度问题
$tax = $total * 0.08; // 金融计算不准确
3. 敏感数据处理
php
// ✅ 正确:敏感信息加密存储
$user->id_card = encryption($idCard);
$user->bank_account = encryption($bankAccount);
// ✅ 正确:显示时部分隐藏
$displayPhone = str_hidden($user->phone, 40);
$displayEmail = str_hidden($user->email, 50, '*', '@');
// ❌ 避免:明文存储敏感信息
$user->id_card = $idCard; // 安全风险
4. 错误处理和调试
php
// ✅ 正确:条件调试
if (App::$debug) {
dd($complexData);
}
// ✅ 正确:异常处理
try {
$encrypted = encryption($data);
} catch (ExceptionBusiness $e) {
App::log()->error('加密失败', ['error' => $e->getMessage()]);
throw new ExceptionBusiness(__('system.encryption_failed'));
}
// ❌ 避免:生产环境调试代码
dd($sensitiveData); // 生产环境安全风险
5. 国际化处理
php
// ✅ 正确:使用翻译函数
return send($response, __('operation.success'), $data);
throw new ExceptionBusiness(__('user.not_found'));
// ✅ 正确:参数化翻译
$message = __('user.welcome', ['name' => $user->name]);
// ❌ 避免:硬编码文本
return send($response, '操作成功', $data); // 不支持国际化
throw new ExceptionBusiness('用户不存在'); // 不支持多语言
这些辅助函数构成了DuxLite框架的工具基础,合理使用它们可以大大提高开发效率,同时确保代码的安全性和可维护性。