
本文介绍如何通过url重写和路由机制,将php电商网站的/product.php?id=product_name式url改为/boroplus-antiseptic-moisturising等语义化路径,无需创建物理目录,仅需.htaccess配合前端控制器即可实现,并说明后端数据获取逻辑。
本文介绍如何通过url重写和路由机制,将php电商网站的/product.php?id=product_name式url改为/boroplus-antiseptic-moisturising等语义化路径,无需创建物理目录,仅需.htaccess配合前端控制器即可实现,并说明后端数据获取逻辑。
要实现类似 Amazon 或 Flipkart 的语义化商品URL(如 /boroplus-antiseptic-moisturising),核心在于移除对 query string 参数(如 ?id=...)的依赖,转而采用路径段(path segment)解析 + 服务端路由的方式。这并非要求你为每个商品手动创建文件夹,而是通过 Apache 的 URL 重写功能,将所有请求统一交由一个入口文件(如 index.php)处理——即「前端控制器(Front Controller)」模式。
✅ 步骤一:配置 .htaccess 启用重写规则
在网站根目录下创建或编辑 .htaccess 文件,添加以下内容(确保服务器已启用 mod_rewrite):
Options +FollowSymLinks
RewriteEngine On
# 排除真实存在的文件和目录(如 CSS、JS、图片等)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 将所有非静态资源请求重写到 index.php
RewriteRule ^(.*)$ index.php [QSA,L]
⚠️ 注意:QSA(Query String Append)标志可保留原始查询参数(如分页、筛选参数),L 表示终止后续规则匹配。
✅ 步骤二:在 index.php 中解析路径并路由
当用户访问 mysite.com/boroplus-antiseptic-moisturising/abc123 时,Apache 会将请求转发至 index.php,此时可通过 $_SERVER['REQUEST_URI'] 获取完整路径:
<?php // index.php —— 统一路由入口
$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = array_filter(explode('/', $requestUri)); // 过滤空字符串(如开头/导致的空项)
if (empty($segments)) {
// 首页逻辑
include 'home.php';
} elseif (count($segments) >= 1) {
$slug = $segments[0]; // 例如 'boroplus-antiseptic-moisturising'
// ✅ 安全建议:仅允许字母、数字、连字符、下划线
if (!preg_match('/^[a-z0-9\-_]+$/', $slug)) {
http_response_code(400);
die('Invalid product slug');
}
// 查询数据库:根据 slug 查找商品(需确保数据库中 product_slug 字段已建立索引)
$pdo = new PDO('mysql:host=localhost;dbname=shop', $user, $pass);
$stmt = $pdo->prepare("SELECT * FROM products WHERE slug = ? AND status = 'active'");
$stmt->execute([$slug]);
$product = $stmt->fetch(PDO::FETCH_ASSOC);
if ($product) {
include 'templates/product-detail.php'; // 渲染商品页
} else {
http_response_code(404);
include 'templates/404.php';
}
}
✅ 关键设计要点与最佳实践
- 数据库字段优化:为产品表添加唯一索引字段 slug(如 boroplus-antiseptic-moisturising),该值应由产品标题自动生成(使用 slugify() 函数转换空格为短横线、剔除特殊字符),并确保全局唯一(冲突时追加数字)。
- 避免 ID 暴露:URL 中不再出现敏感 ID,提升安全性与SEO友好度;但数据库内仍建议保留自增主键 id 用于关联查询。
-
不要重复造轮子:如问题答案所强调,自行实现路由易出错且难维护。生产环境强烈推荐使用成熟框架:
- Laravel:Route::get('/{slug}', [ProductController::class, 'show']);
- Symfony:基于 Symfony\Component\Routing\Matcher\UrlMatcher 构建声明式路由。
- 缓存与性能:对 slug → product 的映射做 Redis 缓存,减少高频数据库查询压力。
通过以上方式,你既能获得简洁、可读、利于SEO的商品URL,又无需管理大量物理目录,同时保持代码结构清晰、扩展性强。











