MVC路由如何工作? [英] How does MVC routing work?

查看:64
本文介绍了MVC路由如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我已经开始更深入地研究MVC(真正的MVC,而不是框架MVC),并且我正在尝试开发一个小型框架.我正在阅读其他框架(例如Symphony和Zend),了解它们如何完成工作,并尝试自己实施.

So I've started studying MVC (real MVC, not framework MVC) a bit more in-depth, and I'm attempting to develop a small framework. I'm working by reading other frameworks such as Symphony and Zend, seeing how they do their job, and attempt to implement it myself.

我被卡住的地方是URL路由系统:

The place where I got stuck was the URL routing system:

<?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)"
    }
},

 */

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

I just can't get my head wrapped around it properly. What is the application workflow from here?

会生成模式,可能是要保存在Request对象下的Route对象,还是什么?如何运作?

The pattern is generated, probably a Route object to be kept under the Request object or something, then what? How does it work?

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

P.S. Looking for a real, well explained answer here. I really want to understand the subject. I would appreciate if someone took the time to write a real elaborate answer.

推荐答案

MVC Router类(是更广泛的 Front Controller 的一部分)分解了HTTP请求的URL,具体来说,路径组件(可能还有查询字符串).

An MVC Router class (which is part of a broader Front Controller) breaks down an HTTP request's URL--specifically, the path component (and potentially the query string).

Router尝试将路径组件的前一个或两个部分与相应的路由组合(Controller/操作[方法]或只是Controller会执行默认操作(方法).

The Router attempts to match the first one, or two, parts of the path component to a corresponding route combination (Controller / Action [method], or just a Controller that executes a default action (method).

动作或命令只是特定Controller方法.

An action, or command, is simply a method off of a specific Controller.

通常有一个abstract Controller和许多Controller子级,每个网页一个(通常来说).

There is usually an abstract Controller and many children of Controller, one for each webpage (generally speaking).

有人可能会说Router还将参数传递给所需的Controller方法,如果URL中存在参数的话.

Some might say that the Router also passes arguments to the desired Controller's method, if any are present in the URL.

注意:面向对象的编程纯粹主义者遵循单一职责原则,可能会争辩说URL的路由组件和调度Controller类是两个单独的职责.在这种情况下,Dispatcher类实际上将实例化Controller并将从客户端HTTP请求派生的任何参数传递给其方法之一.

Note: Object-oriented programming purists, following the Single Responsibility Principle, might argue that routing components of a URL and dispatching a Controller class are two separate responsibilities. In that case, a Dispatcherclass would actually instantiate the Controller and pass one of its methods any arguments derived from the client HTTP request.

示例1:Controller,但没有任何动作或参数.

Example 1: Controller, but no action or arguments.

http://localhost/contact在GET请求中,这可能会显示一个表单.

http://localhost/contact On a GET request, this might display a form.

控制器 =合同

动作 =默认值(通常是index()方法)

Action = Default (commonly an index() method)

=====================

======================

示例2:Controller和操作,但没有参数.

Example 2: Controller and action, but no arguments.

http://localhost/contact/send在POST请求中,这可能会启动服务器端验证并尝试发送消息.

http://localhost/contact/send On a POST request, this might kick of server-side validation and attempt to send a message.

控制器 =合同

动作 =发送

=====================

======================

示例3:Controller,操作和参数.

Example 3: Controller, action, and arguments.

http://localhost/contact/send/sync在POST请求上,这可能会启动服务器端验证并尝试发送消息.但是,在这种情况下,JavaScript可能没有激活.因此,为了支持正常降级,可以告诉ContactController使用支持屏幕重绘并以HTTP标头Content-Type: text/html(而不是Content-Type: application/json)响应的View. sync将作为参数传递给ContactConroller::send().请注意,我的sync示例完全是任意的,并且可以弥补,但我认为这很合适!

http://localhost/contact/send/sync On a POST request, this might kick of server-side validation and attempt to send a message. However, in this case, maybe JavaScript is not active. Thus, to support graceful degradation, you can tell the ContactController to use a View that supports screen redraw and responds with an HTTP header of Content-Type: text/html, instead of Content-Type: application/json. sync would be passed as an argument to ContactConroller::send(). Note, my sync example was totally arbitrary and made up, but I thought it fit the bill!

控制器 =合同

动作 =发送

参数 = [sync]//是,在数组中传递参数!

Arguments = [sync] // Yes, pass arguments in an array!

一个Router类实例化所请求的具体子对象Controller,从 controller实例调用所请求的 method ,并将其传递给控制器​​方法参数(如果有).

A Router class instantiates the requested, concrete child Controller, calls the requested method from the controller instance, and passes the controller method its arguments (if any).

1)您的Router类应首先检查是否有可实例化的具体Controller(使用URL中的名称以及"Controller"一词) ).如果找到了控制器,请测试请求的方法是否存在 (行动).

1) Your Router class should first check to see if there is a concrete Controller that it can instantiate (using the name as found in the URL, plus the word "Controller"). If the controller is found, test for the presence of the requested method (action).

2)如果Router在运行时找不到并加载必要的PHP(使用匹配内. Route类的基本框架如下.

2) If the Router cannot find and load the necessary PHP at runtime (using an autoloader is advised) to instantiate a concrete Controller child, it should then check an array (typically found in another class name Route) to see if the requested URL matches, using regular expressions, any of the elements contained within. A basic skeleton of a Route class follows.

请注意:.*? =零个或多个任意字符,不会被捕获.

Note: .*? = Zero, or more, of any character, non-capturing.

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

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

Why use a regular expression? One is not likely to get reliable matching accomplished for data after the second forward slash in the URL.

/controller/method/param1/param2/...,其中param [x]可能是任何

/controller/method/param1/param2/..., where param[x] could be anything!

警告::当定位数据包含模式定界符(在这种情况下,正斜杠"/"时,最好更改默认的正则表达式模式定界符('/').有效的URL字符将是一个不错的选择.

Warning: It is good practice change the default regular expression pattern delimiter ('/') when targeting data contains the pattern delimiter (in this case, forward slashes '/'. Almost any non-valid URL character would be a great choice.

Router类的方法将遍历Route::routes数组,以查看目标URL与与第二级关联的string value 之间是否存在正则表达式匹配url索引.如果找到匹配项,则Router然后知道要实例化哪个具体的Controller以及要调用的后续方法.参数将根据需要传递给该方法.

A method of the Router class will iterate over the Route::routes array to see if there is a regular expression match between the target URL and the string value associated with a 2nd level url index. If a match is found, the Router then knows which concrete Controller to instantiate and the subsequent method to call. Arguments will be passed to the method as necessary.

始终警惕某些极端情况,例如表示以下内容的网址.

Always be wary of edge cases, such as URLs representing the following.

`/`   // Should take you to the home page / HomeController by default
`''`  // Should take you to the home page / HomeController by default
`/gibberish&^&*^&*%#&(*$%&*#`   // Reject

这篇关于MVC路由如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆