MVC路由如何工作?

Mad*_*iha 20 php model-view-controller routes

所以我开始更深入地研究MVC(真正的MVC,而不是框架MVC),并且我正在尝试开发一个小框架.我正在阅读其他框架,如Symphony和Zend,看看他们是如何完成自己的工作,并尝试自己实现它.

我遇到的地方是URL路由系统:

<?php
namespace Application\Common;

class RouteBuilder {

    public function create($name, $parameters) {
        $route           = new Route($name);
        $route->resource = array_keys($parameters)[0];
        $route->defaults = $parameters["defaults"];
        $notation        = $parameters["notation"];
        $notation = preg_replace("/\[(.*)\]/", "(:?$1)?", $notation);
        foreach ($parameters["conditions"] as $param => $condition) {
            $notation = \str_replace($param, $condition, $notation);
        }

        $notation = preg_replace("/:([a-z]+)/i", "(?P<$1>[^/.,;?\n]+)", $notation);

        //@TODO: Continue pattern replacement!!
    }
}
/* How a single entry looks like
 * "main": {
    "notation": "/:action",
    "defaults": {
        "resource"  :   "Authentication",
    },
    "conditions":   {
        ":action"   :   "(login)|(register)"
    }
},

 */
Run Code Online (Sandbox Code Playgroud)

我只是不能正确地缠绕它.这里的应用程序工作流程是什么?

生成模式,可能是Route要保留在Request对象下的对象,然后是什么?它是如何工作的?

PS在这里寻找一个真实的,解释清楚的答案.我真的很想了解这个主题.如果有人花时间写一个真实精心的答案,我将不胜感激.

w00*_*w00 28

Router类(或Router一些会称之为)检查一个HTTP请求的URL,并尝试其组成成分匹配到混凝土Controller和在该控制器中定义的方法(也称为动作或命令).它还将参数传递给所需Controller的方法(如果URL中存在任何方法).

标准URL:查询字符串格式

Apache HTTP Server中,不使用mod_rewrite,HTTP请求中的URL可能采用查询字符串格式:

class Route
{
    private $routes = [
        ['url' => 'nieuws/economie/.*?', // regular expression.
         'controller' => 'news',
         'action' => 'economie'],
        ['url' => 'weerbericht/locatie/.*?', // regular expression.
         'controller' => 'weather',
         'action' => 'location']
    ];

    public function __contstruct()
    {

    }

    public function getRoutes()
    {
        return $this->routes;
    }
}
Run Code Online (Sandbox Code Playgroud)

重写的URL:所需的格式

在通过Web服务器重写后,URL往往如下所示:

`/`   // Should take you to the home page / HomeController by default
`''`  // Should take you to the home page / HomeController by default
`/gibberish&^&*^&*%#&(*$%&*#`   // Reject
Run Code Online (Sandbox Code Playgroud)

如果没有URL重写,您将需要一个类来解析Controller来自标准URL的查询中的参数.这是abstract Controller班级可能做的第一件事.在这种情况下,它解析Controller为:

  • controller = NewsController
  • 方法=经济学()
  • 参数:[param1,param2]

如果一切顺利,将发生类似于此的事情:

class Route
{
    private $routes = [
        ['url' => 'nieuws/economie/.*?', // regular expression.
         'controller' => 'news',
         'action' => 'economie'],
        ['url' => 'weerbericht/locatie/.*?', // regular expression.
         'controller' => 'weather',
         'action' => 'location']
    ];

    public function __contstruct()
    {

    }

    public function getRoutes()
    {
        return $this->routes;
    }
}
Run Code Online (Sandbox Code Playgroud)

一个Router类实例化的要求,具体孩子Controller,调用请求的方法控制器实例,并通过在控制器方法的参数(如果有的话).

现在,您正在显示的类将所请求的"路由"解析为正确的控制器/操作.所以,例如下面的URL:

`/`   // Should take you to the home page / HomeController by default
`''`  // Should take you to the home page / HomeController by default
`/gibberish&^&*^&*%#&(*$%&*#`   // Reject
Run Code Online (Sandbox Code Playgroud)

...是英文网址.因此查询字符串中的单词news.假设您希望URL以荷兰语运行.

class Route
{
    private $routes = [
        ['url' => 'nieuws/economie/.*?', // regular expression.
         'controller' => 'news',
         'action' => 'economie'],
        ['url' => 'weerbericht/locatie/.*?', // regular expression.
         'controller' => 'weather',
         'action' => 'location']
    ];

    public function __contstruct()
    {

    }

    public function getRoutes()
    {
        return $this->routes;
    }
}
Run Code Online (Sandbox Code Playgroud)

这意味着Controller将调用具体Dispatcher,但它不存在.这就是你的榜样:Controller课堂.

1)您的Controller类应首先检查是否存在http://localhost/contact可以实例化的具体内容(使用URL中的名称以及"Controller"一词).如果找到控制器,则测试是否存在所请求的方法(操作).

2)如果index()无法在运行时找到并加载必要的PHP(建议使用自动加载器)来实例化一个具体的Controller子进程,那么它应该检查一个数组(通常在另一个类名中找到http://localhost/contact/send)以查看请求的URL是否匹配,使用常规表达式,包含在其中的任何元素.类的基本骨架Controller如下.

注意:http://localhost/contact/send/sync=任何字符的零或更多,非捕获.

`/`   // Should take you to the home page / HomeController by default
`''`  // Should take you to the home page / HomeController by default
`/gibberish&^&*^&*%#&(*$%&*#`   // Reject
Run Code Online (Sandbox Code Playgroud)

为什么要使用正则表达式?在URL中的第二个正斜杠之后,不太可能获得对数据的可靠匹配.

ContactController,param [x]可以是任何东西!

警告:当目标数据包含模式分隔符(在这种情况下,正斜杠'/')时,最好更改默认的正则表达式模式分隔符('/').几乎任何无效的URL字符都是一个很好的选择.

View该类的方法将遍历Content-Type: text/html数组以查看目标URL与与第二级索引关联的Content-Type: application/json 之间是否存在正则表达式匹配sync.如果找到匹配,ContactConroller::send()那么然后知道sync要实例化哪个具体以及随后要调用的方法.必要时,参数将传递给方法.

始终警惕边缘情况,例如表示以下内容的URL.

class Route
{
    private $routes = [
        ['url' => 'nieuws/economie/.*?', // regular expression.
         'controller' => 'news',
         'action' => 'economie'],
        ['url' => 'weerbericht/locatie/.*?', // regular expression.
         'controller' => 'weather',
         'action' => 'location']
    ];

    public function __contstruct()
    {

    }

    public function getRoutes()
    {
        return $this->routes;
    }
}
Run Code Online (Sandbox Code Playgroud)