生成 url slug 的核心是用双步正则法:先保留数字点(如2.5)并清除其他非字母数字非空格字符,再将空白统一为下划线,最后转小写;需加 u 修饰符支持 utf-8,laravel 中建议封装为服务并结合模型事件自动填充,生产环境需截断、去重与缓存适配。

生成 URL Slug 的核心是把任意标题安全转成小写、去杂、空格变分隔符的纯 ASCII 字符串,同时保留关键语义(比如 1.0 中的点)。不靠黑盒库、不硬编码逻辑,用可读、可测、可维护的方式落地。
基础正则双步法:保点、清杂、统一下划线
适用于原生 PHP 或轻量项目,无需额外依赖。关键是分两步处理,避免“一刀切”误删数字点:
- 第一步:
/(\d\.\d)|\.|[^\s\w]/g—— 捕获并保留 数字+点+数字(如2.5),其余所有点和非字母数字非空格字符全清除;捕获组$1确保只回填合法点 - 第二步:
/\s+/g—— 将连续空白(空格、制表、换行)统一替换为单个下划线 - 最后加
strtolower()转小写,符合 URL 标准
示例函数:
function toUrlSlug(string $str): string {return preg_replace('/(\d\.\d)|\.|[^\s\w]/', '$1', $str)
=> preg_replace('/\s+/', '_', $str)
=> strtolower($str);
}
多字节安全增强:兼容中文、emoji、带音调字符
原生 preg_replace 默认按字节匹配,遇到 UTF-8 字符(如 你好 v2.1)会乱码或截断。需显式启用 u 修饰符,并改用 Unicode 属性类:
- 将第一步正则升级为:
/(\d\.\d)|\.|[^\s\p{L}\p{N}_]/u——\p{L}匹配任意语言字母,\p{N}匹配任意数字,u启用 UTF-8 模式 - 第二步保持
/\s+/u即可,\s在 u 模式下也支持 Unicode 空白 - 若需拼音转换(如
你好 → ni-hao),建议引入overtrue/pinyin库,在正则前先做预处理
Laravel 场景:自定义 Slugger + 模型钩子一体化
在 Laravel 中,推荐通过服务容器解耦 slug 逻辑,而非在模型里硬写 str_slug():
- 创建
app/Services/SlugGenerator.php,实现__invoke(string $name): string,内部复用上述双步正则(带 u 修饰符) - 在
config/tags.php或AppServiceProvider中绑定:$this->app->bind(SlugifierInterface::class, SlugGenerator::class) - 在模型中用
creating事件自动填充:$model->slug = app(SlugifierInterface::class)($model->name);
生产环境兜底策略:长度限制、唯一性校验、缓存友好
真实业务中,slug 不仅要“能生成”,还要“能上线”:
-
截断防溢出:生成后用
substr($slug, 0, 120)限制最大长度(数据库字段常见 191 字符,留余量) -
唯一性保障:插入前查重,冲突时追加短随机串(如
-abc12)或时间戳毫秒后三位 - 缓存键友好:slug 作为 Redis 缓存 key 时,确保不含特殊符号;上述正则已保证只含小写字母、数字、下划线,可直接使用
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











