首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

CodeIgniter _remap() 方法詳解:路由重寫、隱藏方法名與權限控制兩大實戰場景

     編輯:PHP 相關知識

CodeIgniter 的 _remap() 是控制器級的「萬能路由攔截器」,允許完全自定義 URI 到方法的映射關係。本文解析其機制,並展示「隱藏真實方法名」與「方法級權限控制」兩大經典應用場景。

一、核心機制

  • 控制器中定義 public function _remap($method, $params = []) 後,**所有**對該控制器的請求均進入此方法。
  • URI 第二段(原本對應方法名)作為 $method 參數傳入,後續段作為 $params 陣列。
  • 原有的「URI 段 → 方法名」自動映射**完全失效**,開發者需在 _remap() 內手動分發。

二、場景一:隱藏真實方法名(URL 美化/安全)

需求:將 /blog/say 對外呈現為 /blog/hello,內部仍調用 say()。

class Blog extends CI_Controller {
    public function _remap($method, $params = []) {
        // 映射表:外部名 => 內部方法
        $map = [
            'hello' => 'say',
            'list'  => 'index',
            'view'  => 'detail',
        ];

        $internalMethod = $map[$method] ?? $method; // 無映射則直接用原名

        if (method_exists($this, $internalMethod)) {
            return call_user_func_array([$this, $internalMethod], $params);
        }

        show_404(); // 方法不存在
    }

    public function say($name = 'World') {
        echo "Hello, $name!";
    }
    // 原本的 say() 現在無法直接通過 /blog/say 訪問
}

效果:

  • /blog/hello/John → 顯示 "Hello, John!"
  • /blog/say/John → 404(被隱藏)

三、場景二:方法級權限控制(RBAC 簡易實現)

class Admin extends CI_Controller {
    public function _remap($method, $params = []) {
        // 1. 公開方法白名單(無需登入)
        $public = ['login', 'captcha', 'forgot_password'];
        if (in_array($method, $public, true)) {
            return $this->$method(...$params);
        }

        // 2. 檢查登入
        if (empty($this->session->userdata('admin_id'))) {
            return $this->login(); // 或 redirect('admin/login')
        }

        // 3. 權限檢查:角色 -> 允許方法列表
        $role = $this->session->userdata('role'); // 'super', 'editor', 'viewer'
        $acl = [
            'super'  => ['*'],                    // 所有權限
            'editor' => ['article_*', 'category_*', 'media_*'],
            'viewer' => ['article_view', 'dashboard'],
        ];

        $allowed = $acl[$role] ?? [];
        $hasAccess = false;
        foreach ($allowed as $pattern) {
            if ($pattern === '*' || fnmatch($pattern, $method)) {
                $hasAccess = true;
                break;
            }
        }

        if ($hasAccess && method_exists($this, $method)) {
            return $this->$method(...$params);
        }

        // 4. 無權限
        show_error('權限不足:' . $method, 403);
    }

    public function article_list() { /* ... */ }
    public function article_edit($id) { /* ... */ }
    public function article_view($id) { /* ... */ }
    public function user_manage() { /* ... */ }
    // ...
}

四、進階技巧與注意事項

  1. 保留預設行為:若僅需微調,可在 _remap 末尾 `return call_user_func_array([$this, $method], $params);` 維持原有映射。
  2. 參數類型:$params 為數值索引陣列,需用 `...` 解包傳遞(PHP 5.6+)。
  3. 效能:_remap 每請求執行一次,邏輯勿過重;權限檢查建議快取 ACL 規則。
  4. 路由衝突:`application/config/routes.php` 中的自定義路由優先於 _remap,注意優先級。
  5. CSRF 保護:POST 請求仍需通過 CI CSRF 驗證,_remap 不影響此機制。

五、總結

_remap() 是 CodeIgniter 靈活路由的核心擴展點。**適度使用**可實現 URL 語義化、內部結構隱藏、集中式權限控制。但過度濫用會導致控制器邏輯膨脹、難以追蹤,建議:簡單映射用 routes.php,複雜權限/別名用 _remap,核心業務邏輯保持在具體方法中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved