2013-10-28 35 views
4

我目前工作的一個框架唯一項目,我有我的路線設置這樣的:路由從沒有URL操作(即主頁)

--- 
Name: app 
After: 'framework/routes' 
--- 
Director: 
    rules: 
    '$Action/$ID/$OtherID': 'MainController' 

和我的控制器是這樣的:

<?php 

class MainController extends Controller { 

    static $allowed_actions = array('build'); 

    public function init() { 
     parent::init(); 
    } 

    public function index() { 
     echo $this->Action; 
     die; 
    } 

    public function build(){ 
     echo 'build'; 
     die; 
    } 

該網站始終吐出index當我去/build但是參觀/adadsa/build會給我echo'ing build,我該怎麼設置我的路線,該URL /顯示的理想結果10從我的控制器,和/build顯示結果從構建?

+0

你有沒有試過看看規則是如何與'debug_request = 1'匹配的,這將有助於你理解事物是如何匹配的。 – colymba

回答

6

要將/映射到您的控制器,您需要提供一條「空」路線。在這種情況下,這將是:

Director: 
    rules: 
    '': 'MainController' 

對於其他的路線,你遇到時會發生什麼DirectorrulesControllerurl_handlers相遇。在解決這個問題的方法是不處理url_handlers

將以下兩種方法添加到您的MainController類應該這樣做。它們基於RequestHandler中的方法3.1 handleRequestController中的handleRequest方法,所以應該按預期工作,但我沒有測試它們。

public function handleRequest(SS_HTTPRequest $request, DataModel $model) { 
    if(!$request) user_error("Controller::handleRequest() not passed a request!", E_USER_ERROR); 

    $this->pushCurrent(); 
    $this->urlParams = $request->allParams(); 
    $this->request = $request; 
    $this->response = new SS_HTTPResponse(); 
    $this->setDataModel($model); 

    $this->extend('onBeforeInit'); 

    // Init 
    $this->baseInitCalled = false; 
    $this->init(); 
    if(!$this->baseInitCalled) { 
     user_error("init() method on class '$this->class' doesn't call Controller::init()." 
      . "Make sure that you have parent::init() included.", E_USER_WARNING); 
    } 

    $this->extend('onAfterInit'); 

    // If we had a redirection or something, halt processing. 
    if($this->response->isFinished()) { 
     $this->popCurrent(); 
     return $this->response; 
    } 

    $body = $this->handleLocalRequest($request, $model); 
    if($body instanceof SS_HTTPResponse) { 
     if(isset($_REQUEST['debug_request'])) { 
      Debug::message("Request handler returned SS_HTTPResponse object to $this->class controller;" 
       . "returning it without modification."); 
     } 
     $this->response = $body; 

    } else { 
     if($body instanceof Object && $body->hasMethod('getViewer')) { 
      if(isset($_REQUEST['debug_request'])) { 
       Debug::message("Request handler $body->class object to $this->class controller;" 
        . "rendering with template returned by $body->class::getViewer()"); 
      } 
      $body = $body->getViewer($request->latestParam('Action'))->process($body); 
     } 

     $this->response->setBody($body); 
    } 


    ContentNegotiator::process($this->response); 
    HTTP::add_cache_headers($this->response); 

    $this->popCurrent(); 
    return $this->response; 
} 

protected function handleLocalRequest(SS_HTTPRequest $request, DataModel $model) { 
    $this->request = $request; 
    $this->setDataModel($model); 

    $action = $request->latestParam('Action'); 

    if(!$action) { 
     if(isset($_REQUEST['debug_request'])) { 
      Debug::message("Action not set; using default action method name 'index'"); 
     } 
     $action = "index"; 
    } else if(!is_string($action)) { 
     user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR); 
    } 

    $className = get_class($this); 

    try { 
     if(!$this->hasAction($action)) { 
      return $this->httpError(404, "Action '$action' isn't available on class $className."); 
     } 
     if(!$this->checkAccessAction($action) || in_array(strtolower($action), array('run', 'init'))) { 
      return $this->httpError(403, "Action '$action' isn't allowed on class $className."); 
     } 
     $result = $this->handleAction($request, $action); 
    } catch (SS_HTTPResponse_Exception $e) { 
     return $e->getResponse(); 
    } catch(PermissionFailureException $e) { 
     $result = Security::permissionFailure(null, $e->getMessage()); 
    } 

    if($result instanceof SS_HTTPResponse && $result->isError()) { 
     if(isset($_REQUEST['debug_request'])) Debug::message("Rule resulted in HTTP error; breaking"); 
     return $result; 
    } 

    // If we return a RequestHandler, call handleRequest() on that, even if there is no more URL to 
    // parse. It might have its own handler. However, we only do this if we haven't just parsed an 
    // empty rule ourselves, to prevent infinite loops. Also prevent further handling of controller 
    // actions which return themselves to avoid infinite loops. 
    $matchedRuleWasEmpty = !$request->latestParam('Action'); 
    $resultIsRequestHandler = is_object($result) && $result instanceof RequestHandler; 

    if($this !== $result && !$matchedRuleWasEmpty && $resultIsRequestHandler) { 
     $returnValue = $result->handleRequest($request, $model); 

     // Array results can be used to handle 
     if(is_array($returnValue)) $returnValue = $this->customise($returnValue); 

     return $returnValue; 

    // If we return some other data, and all the URL is parsed, then return that 
    } else if($request->allParsed()) { 
     return $result; 

    // But if we have more content on the URL and we don't know what to do with it, return an error. 
    } else { 
     return $this->httpError(404, "I can't handle sub-URLs of a $this->class object."); 
    } 

    return $this; 
} 

從目前存在什麼主要區別是在handleLocalRequest,它取代了RequestHandler->handleRequest方法。在這裏,我們硬編碼支持$Action/$ID/$OtherID導演級別的規則,而不是檢查本地url_handlers,然後嘗試與這些規則匹配。這意味着無論Director匹配是直接用於找出要調用的操作以及其他參數是什麼。