Silverstripe 从无url路由到操作(即主页)

Silverstripe 从无url路由到操作(即主页),silverstripe,Silverstripe,我目前正在进行一个只支持框架的项目,我的路线设置如下: --- Name: app After: 'framework/routes' --- Director: rules: '$Action/$ID/$OtherID': 'MainController' <?php class MainController extends Controller { static $allowed_actions = array('build'); public fu

我目前正在进行一个只支持框架的项目,我的路线设置如下:

---
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;
    }
我的控制器是这样的:

---
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;
    }

要将
/
映射到控制器,您需要提供一条“空”路线。在这种情况下,这将是:

Director:
  rules:
    '': 'MainController'
对于其他路由,当
Director
规则
控制器
url\u处理程序
相遇时,您会遇到什么情况。解决这个问题的方法是不要处理
url\u处理程序

将以下两个方法添加到
MainController
类应该可以做到这一点。它们基于
RequestHandler
中的3.1
handleRequest
方法和
Controller
中的
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\u处理程序,然后尝试与之匹配。这意味着无论
Director
匹配什么,都将直接用于确定要调用的操作以及其他参数是什么。

您是否尝试查看规则与
debug\u request=1
的匹配情况,这将帮助您了解匹配情况。