我正在尝试编写自己的路由器,因为我开始了我的MVC之旅。我有它的基础知识,但是当涉及到其他URL参数时,我遇到了一些麻烦。根据我迄今为止编写代码的方式,我不知道如何处理这个问题。
这是我的代码:
公共/ index.php的
<?php
include '../config.php';
include '../routes.php';
include '../app/controllers/RouteController.php';
$rc = new RouteController($config, $routes);
?>
的config.php
<?php
$config['app_url'] = 'http://localhost/mymvc'; // no ending slashes
?>
routes.php文件
<?php
$routes = array();
$routes[] = array('url' => '', 'controller' => 'HomeController');
$routes[] = array('url' => 'leads', 'controller' => 'LeadController');
$routes[] = array('url' => 'leads/page/[0-9]', 'controller' => 'LeadController', 'method' => 'update', 'params' => 'page=$1');
$routes[] = array('url' => 'leads/create', 'controller' => 'LeadController', 'method' => 'create');
$routes[] = array('url' => 'leads/update/[0-9]', 'controller' => 'LeadController', 'method' => 'update', 'params' => 'id=$1');
?>
应用\控制器\ RouteController.php
<?php
class RouteController {
private $config;
private $routes;
private $url;
private $controller = null;
private $method = null;
private $params = array();
public function __construct ($config, $routes) {
$this->config = $config;
$this->routes = $routes;
$this->setUrl();
$route_exists = false;
// check if route has been declared for security
foreach ($this->routes as $route) {
if ($route['url'] == $this->url) {
$this->controller = $route['controller'];
$this->method = isset($route['method']) ? $route['method'] : null;
$this->params = isset($route['params']) ? $route['params'] : array();
$route_exists = true;
}
}
// send them to app index if route does not exist
if ($route_exists) {
$this->route();
}
else {
header('Location: '.$this->config['app_url']);
die('route does not exist');
}
}
private function setUrl () {
$url = trim($_GET['url'], '/');
$url = filter_var($url, FILTER_SANITIZE_URL);
$this->url = $url;
}
private function route () {
// include '../controllers/'.$this->controller;
// do stuff with the controller, method, params
}
}
?>
现在,如果你查看routes.php文件,你可以从我的代码中看到它对以下路由没有问题:
<?php
$routes = array();
$routes[] = array('url' => '', 'controller' => 'HomeController');
$routes[] = array('url' => 'leads', 'controller' => 'LeadController');
$routes[] = array('url' => 'leads/create', 'controller' => 'LeadController', 'method' => 'create');
?>
我需要弄清楚的是如何在路线中处理其他参数。这些是我试图找到解决方案的有问题的路线:
$routes[] = array('url' => 'leads/page/[0-9]', 'controller' => 'LeadController', 'method' => 'update', 'params' => 'page=$1');
$routes[] = array('url' => 'leads/update/[0-9]', 'controller' => 'LeadController', 'method' => 'update', 'params' => 'id=$1');
非常感谢任何帮助。谢谢:))
答案 0 :(得分:2)
将尝试演示我的例子。 Bootstrap
班级:
$uri = Router::make_uri();
if ($params = Router::match_uri($uri))
{
$controller = ucwords($params['controller']).'_Controller';
$method = $params['method'];
unset($params['controller'], $params['method']);
if (class_exists($controller))
{
if (method_exists($controller, $method))
{
call_user_func_array(array(new $controller, $method), $params);
}
else
{
Error::throw_error('Bootstrap : No method found '.$method);
}
}
else
{
Error::throw_error('Bootstrap : No controller found '.$controller);
}
}
else
{
Error::throw_error('Bootstrap : No route found '.$uri);
}
Router
班级:
public static function make_uri()
{
if(!empty($_SERVER['PATH_INFO']))
{
self::$uri = $_SERVER['PATH_INFO'];
}
elseif (!empty($_SERVER['REQUEST_URI']))
{
self::$uri = $_SERVER['REQUEST_URI'];
//removing index
if (strpos(self::$uri, 'index.php') !== FALSE)
{
self::$uri = str_replace(self::$uri, 'index.php', '');
}
}
return parse_url(trim(self::$uri, '/'), PHP_URL_PATH);
}
public static function match_uri($uri)
{
require(APP_DIR.DIR_SEP.'system'.DIR_SEP.'config'.DIR_SEP.'Routes.php');
if (empty($routes))
{
Error::throw_error('Routes must not be empty');
}
self::$routes = $routes;
$params = array();
foreach ($routes as $route)
{
//we keep our route uri in the [0] position
$route_uri = array_shift($route);
$regex_uri = self::make_regex_uri($route_uri);
if (!preg_match($regex_uri, $uri, $match))
{
continue;
}
else
{
foreach ($match as $key => $value)
{
if (is_int($key))
{
//removing preg_match digit keys
continue;
}
$params[$key] = $value;
}
//if no values are set, load default ones
foreach ($route as $key => $value)
{
if (!isset($params[$key]))
{
$params[$key] = $value;
}
}
break;
}
}
return $params;
}
private static function make_regex_uri($uri)
{
$reg_escape = '[.\\+*?[^\\]${}=!|]';
$expression = preg_replace('#'.$reg_escape.'#', '\\\\$0', $uri);
if (strpos($expression, '(') !== FALSE)
{
$expression = str_replace(array('(', ')'), array('(?:', ')?'), $expression);
}
$reg_segment = '[^/.,;?\n]++';
$expression = str_replace(array('<', '>'), array('(?P<', '>'.$reg_segment.')'), $expression);
return '#^'.$expression.'$#uD';
}
$routes
$routes['password'] = array(
'password(/<hash>)',
'controller' => 'account',
'method' => 'password',
'hash' => ''
);
评论:
Bootstrap
类接收请求并调用返回当前Router::make_uri
的静态URL
。$uri
与预设的$routes
数组匹配。如果任何路由的正则表达式与当前URL
匹配,则传递的值和默认值(如果未设置传递值)将添加到$params
,这将在成功的正则表达式匹配时返回。$params
现在具有匹配路线中定义的所有参数 - Controller
,Method
和额外的参数,例如$hash
。进行相应的调用(如果存在类和方法)
Class Account_Controller
{
public function password($hash)
{
echo $hash;
}
}