在微博類應用中,常見需求:用戶在內容中 @用戶名,點擊跳轉到該用戶主頁。若直接用 /user/index/uname/張三,URL 過長且不美觀。本文展示如何結合 ThinkPHP 的 空操作(_empty) 與 路由配置,實現 /user/張三 這樣簡潔的用戶鏈接。
<?php
function parseAtUsers(string $content): string {
$pattern = '/@(\S+)\s/u'; // 匹配 @用戶名 格式
return preg_replace_callback($pattern, function ($matches) {
$username = $matches[1];
// 生成簡短鏈接:/user/用戶名
$url = __APP__ . '/user/' . urlencode($username);
return "@{$username}";
}, $content);
}
// 測試
$content = "測試內容 @張三 @李四 你好";
echo parseAtUsers($content);
// 輸出: 測試內容 @張三 @李四 你好
?>
當訪問 /user/張三 時,ThinkPHP 找不到 張三Action,會自動調用 _empty() 方法,並將 張三 作為參數傳入。
<?php
namespace Home\Controller;
use Think\Controller;
class UserController extends Controller {
// 空操作:捕獲所有不存在的 action
public function _empty($name) {
$this->_redirectToUserProfile($name);
}
// 內部處理:根據用戶名查找 UID 並跳轉
private function _redirectToUserProfile($username) {
// 解碼 URL 編碼的中文用戶名
$username = urldecode($username);
$uid = M('UserInfo')->where(['username' => $username])->getField('uid');
if (!$uid) {
// 用戶不存在,跳轉首頁或 404
$this->redirect('Index/index');
return;
}
// 跳轉到 /uid 格式(如 /12345),由路由處理
$this->redirect('/' . $uid);
}
}
?>
在 Conf/config.php 中開啟路由並定義規則:
<?php
return [
// 開啟路由
'URL_ROUTER_ON' => true,
// 路由規則
'URL_ROUTE_RULES' => [
// 匹配 /數字 格式,映射到 User/index 並傳 uid 參數
// 正則 :id\d 表示名為 id 的參數只匹配數字
':id\d' => 'User/index', // 訪問 /12345 實際執行 UserController->index(uid=12345)
// 也可顯式寫法
// '/:uid' => ['User/index', ['uid' => '\d+']],
],
];
?>
<?php
class UserController extends Controller {
// ... _empty 方法 ...
// 用戶主頁入口:/12345 經路由映射至此
public function index($uid) {
$user = M('UserInfo')->find($uid);
if (!$user) $this->error('用戶不存在');
$this->assign('user', $user);
$this->display();
}
}
?>
用戶點擊鏈接: /user/張三
↓
ThinkPHP 路由嘗試匹配 → 無靜態規則匹配
↓
UserController 找不到 "張三Action"
↓
自動調用 _empty('張三')
↓
_empty() 查詢數據庫獲取 uid=1001
↓
redirect('/1001')
↓
路由規則 ':id\d' => 'User/index' 匹配成功
↓
執行 UserController->index(uid=1001)
↓
渲染用戶主頁視圖
| 技術點 | 作用 |
|---|---|
_empty($name) | 捕獲不存在的 Action,參數 $name 為調用的方法名 |
urldecode() | 處理中文用戶名 URL 編碼問題 |
redirect('/' . $uid) | 跳轉到純數字路徑,觸發路由規則 |
':id\d' => 'User/index' | 正則路由:匹配純數字,綁定到 User/index 並傳參 |
URL_ROUTER_ON | 必須開啟路由功能 |
若用戶名包含特殊字符,可調整路由正則:
'URL_ROUTE_RULES' => [
// 匹配 /user/用戶名 格式,用戶名允許中英文數字下劃線
'user/:name' => ['User/profile', ['name' => '[\w\x{4e00}-\x{9fa5}]+']],
// 然後在 profile 方法中直接按 name 查詢
// public function profile($name) { ... }
],
_empty 參數已自動 urldecode,但建議顯式調用一次保險。URL_CASE_INSENSITIVE=true。這種模式充分發揮了 ThinkPHP 路由與空操作的靈活性,實現了 RESTful 風格的簡潔 URL,提升用戶體驗與 SEO 友好度。