PHP中前端页面的URL路由模式

PHP中前端页面的URL路由模式,php,url-routing,Php,Url Routing,我正在创建一个MySQL数据库驱动的PHP(W)CMS应用程序,它遵循MVC模式。首先看一下框架: MVC框架处理请求并根据URL决定加载/调用什么,如:http://domain.com/user/details/121将加载并实例化用户控制器对象,并使用作为参数传递的用户ID调用其详细信息(121)方法,然后实例化用户模型和“ask”它使用121 userid来获取用户的详细数据,最后用视图显示结果。这是MVC体系结构的基本概念。没什么特别的,现在一切都清楚了 虽然这将是一个CMS,但我想处

我正在创建一个MySQL数据库驱动的PHP(W)CMS应用程序,它遵循MVC模式。首先看一下框架: MVC框架处理请求并根据URL决定加载/调用什么,如:
http://domain.com/user/details/121
将加载并实例化
用户
控制器对象,并使用作为参数传递的用户ID调用其
详细信息(121)
方法,然后实例化
用户模型
和“ask”它使用121 userid来获取用户的详细数据,最后用
视图显示结果。这是MVC体系结构的基本概念。没什么特别的,现在一切都清楚了

虽然这将是一个CMS,但我想处理一个
页面
模型。具有必要权限(主要是管理员和/或root)的用户可以在页面上执行基本CRUD操作和其他内容,例如: 我可以创建一个包含以下内容的页面:

  • tile=‘关于我们’(这将显示为页面标题或浏览器选项卡的标题,如HTML标题和h1标记)
  • URL命名='*about_-us*'(这将是URI端点,如:
    http://domain.com/about_us
  • 引用名称=‘我们是谁’(这是菜单栏中显示的文本)
  • 页面内容='lorem ipsum…'(页面的实际内容…由WYSIWYG html文本编辑器提供)
  • 还有更多的选项,如构建页面结构,在父页面下分配子页面,或创建页面起始页(这意味着如果我将“关于我们”设置为起始页,则
    http://domain.com
    将自动调用加载该页面内容)
或者我可以修改这些属性,甚至可以删除页面…等等


MVC框架在处理前端调用和后端调用之间没有区别。 例如,我们有一些请求:

  • http://domain.com/user/details/121
  • http://domain.com/about_us
  • http://domain.com/our_products/1255
第一个将加载一个后端控制器,如我前面所述, 但其他人将加载前端内容。 当引导加载适当的控制器/操作时,我们会查找实际的控制器文件,如上例所示:

  • /controllers/Users.php
  • /controllers/About_us.php
  • /controllers/Our_products.php
第一个可以加载,因为它是以前编写的“静态”控制器,但About_us和我们的_产品不是现有的控制器,因此如果无法加载控制器,引导程序将搜索数据库,如果存在具有相同URL拒绝的页面(例如:About_us,我们的_产品)。如果有,我们加载一个通用的FrontEndController并显示请求的页面数据,如果没有,则显示404错误

我这样做是因为我希望引导程序以相同的方式处理所有请求,但我不希望每个前端URL强制包含
FrontEndController
(例如:
http://domain.com/FrontEndController/our_products/1255
)。这就是我对用户隐藏它的方式,因此URL可以保持更友好的用户界面。我的问题是:这是一个好的做法吗?或者有没有其他合适的方法

MVC框架处理请求,并根据URL决定加载/调用什么

您通常会拥有某种类型的
路由器
调度程序
类。路由器将接受
用户/details/121
,解析它并返回
路由

$route = $router->route( $request->getUri() );
路由器可以保存配置值,如URI中允许的空格字符、默认允许的字符等

您还可以向路由器添加自定义路由

$router->addRoutes($routes);
自定义管线可以是简单的关联数组

$routes['requested-uri'] = 'custom-route'
在上面的示例中,您说当他们访问网站的根目录时,您希望他们实际看到关于我们的页面,以便可以这样做:

$router->addRoutes([
    '' => 'about-us
]);
这意味着当URI为“”时(空白),则转到“关于我们”路径。它不应该进行重定向,只是透明地加载不同的路由,同时保持客户端web浏览器中的URI不变

路由显然更复杂,使用添加到路由集合中的路由对象可以实现更高级的自定义路由和更多的控制。一些框架使用注释和各种不同的方式来实现灵活的路由

然后,调度器可以接受从路由器返回的路由并对其进行分派。这意味着验证请求的路由是否实际存在,即控制器文件是否存在,以及控制器中请求的方法是否存在

$view = $dispatcher->dispatch($route);
Dispatcher::Dispatch()方法中:

// Check if the controller file exists.
// Instantiate the controller file, preferably using a controller factory.
// Check if the controller method exists.

// Call the controller method
call_user_func_array([$controller, $route->getMethod()], $route->getParams());

$view = $controller->getView();
$action = $route->getAction();

// Call the view method.
if( method_exists($view, $action) ) {
    $view->$action();
}

return $view;
我发现以下是处理控制器方法/操作的一种非常容易理解的方法。假设您有一个登录控制器,在表单中发送登录详细信息时,用户首先向其发送GET请求,然后向其发送POST请求

public function getIndex() { }

public function postIndex() {
    $username = $this->request->post('username');
    $password = $this->request->post('password');
}
方法名称前面的getpost是请求类型,这可以防止您执行类似操作

public function index() {

    if( $this->request->getType() === 'POST' ) {
        $username = $this->request->post('username');
        $password = $this->request->post('password');
    }
}
它还为您提供了对授权的更多控制(如果您在路由层这样做的话),因为您可以轻松地允许用户向控制器发送GET请求,但拒绝他们发送POST请求

每个控制器都与视图有一对一的关系。视图在构造时被注入控制器,最好使用控制器工厂

当您发送GET请求
http://domain.com/user/details/121
是指路由器会分解URI并将其转换为针对
用户
控制器的路由,
getDetails()
方法带有参数
121
,调度器检查控制器和方法是否存在,然后调用提供用户ID作为参数的方法,控制器设置
public function getDetails($userId) {
    $this->getView()->setUserId( (int)$userId );
}
public function details() {

    // Fetch the user by using the previously set user ID from the controller.
    // If he doesn't exist set an error template, set the response code to 404, 
    // or redirect. Do whatever you want really.

    $this->setTitle('User Details');

    // Build template objects, bind the fetched user data to main template.
}