【问题标题】:How can I make a router in PHP?如何在 PHP 中制作路由器?
【发布时间】:2016-06-06 00:53:12
【问题描述】:

我目前正在为我的一个项目开发路由器,我需要执行以下操作:

例如,假设我们有这个设置路线数组:

$routes = [
    'blog/posts' => 'Path/To/Module/Blog@posts',
    'blog/view/{params} => 'Path/To/Module/Blog@view',
    'api/blog/create/{params}' => 'Path/To/Module/API/Blog@create'
];

然后,如果我们通过:http://localhost/blog/posts 传递此 URL,它将调度 blog/posts 路由 - 这很好。

现在,当涉及到需要参数的路由时,我所需要的只是一种实现传递参数能力的方法,(即http://localhost/blog/posts/param1/param2/param3 和添加api 以创建http://localhost/api/blog/create/ 的能力目标 API 调用,但我很难过。

【问题讨论】:

  • 我敢建议你选择现有的路由器吗?
  • @Progrock 如果现有路由器具有与我需要的功能相似的功能,我很乐意将其作为基础,但如果可能的话,我更愿意构建一个完全符合我的标准的路由器。
  • 不清楚你想用路由器做什么,你的意思是重定向吗?这是您在服务器(apache、nginx 等)上执行的操作,或者您可以使用 slug 作为主键,使用任何路由器作为值并将其保存在 memcache 上。稍后只需通过当前 url 查询并重定向。
  • 路由是一个非常通用的任务——你可能有哪些标准没有在Symfony路由中实现? (作为单独的包提供symfony.com/doc/current/book/routing.html
  • 我希望我们可以跳过通常的“你为什么不使用现有的”响应,有点多余。很可能这里的每个人都知道有现有的路由器。有时人们只是想自己做,为了学习,或者只是因为,谁在乎。它只是居高临下的 TBH。

标签: php url-rewriting url-routing


【解决方案1】:

这是一个基本版本 - 只是一个展示功能的概念版本,我不建议在生产环境中使用它。

$routes = [
    'blog/view' => 'Example@index',
    'api/forum/create' => 'other.php'
];

$url = explode('/', $_GET['url']);

if (isset($url[0]))
{
    if ($url[0] == 'api')
    {
        $params = array_slice($url, 3);
        $url = array_slice($url, 0, 3);
    }
    else
    {
        $params = array_slice($url, 2);
        $url = array_slice($url, 0, 2);
    }
}

$url = implode('/', $url);

if (array_key_exists($url, $routes))
{
    $path = explode('/', $routes[$url]);
    unset($path[count($path)]);
    $segments = end($path);
    $segments = explode('@', $segments);

    $controller = $segments[0];
    $method = $segments[1];

    require_once APP_ROOT . '/app/' . $controller . '.php';
    $controller = new $controller;

    call_user_func_array([$controller, $method], $params);  
}

【讨论】:

    【解决方案2】:

    这是一些基本的东西,目前路由可以有一个模式,如果应用程序路径以该模式开头,那么它就是匹配的。路径的其余部分变成了参数。

    <?php
    class Route
    {
        public $name;
        public $pattern;
        public $class;
        public $method;
        public $params;
    }
    
    class Router
    {
        public $routes;
    
        public function __construct(array $routes)
        {
            $this->routes = $routes;
        }
    
        public function resolve($app_path)
        {
            $matched = false;
            foreach($this->routes as $route) {
                if(strpos($app_path, $route->pattern) === 0) {
                    $matched = true;
                    break;
                }
            }
    
            if(! $matched) throw new Exception('Could not match route.');
    
            $param_str = str_replace($route->pattern, '', $app_path);
            $params = explode('/', trim($param_str, '/'));
            $params = array_filter($params);
    
            $match = clone($route);
            $match->params = $params;
    
            return $match;
        }
    }
    
    class Controller
    {
        public function action()
        {
            var_dump(func_get_args());
        }
    }
    
    $route = new Route;
    $route->name    = 'blog-posts';
    $route->pattern = '/blog/posts/';
    $route->class   = 'Controller';
    $route->method  = 'action';
    
    $router = new Router(array($route));
    $match  = $router->resolve('/blog/posts/foo/bar');
    
    // Dispatch
    if($match) {
        call_user_func_array(array(new $match->class, $match->method), $match->params);
    }
    

    输出:

    array (size=2)
      0 => string 'foo' (length=3)
      1 => string 'bar' (length=3)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      • 2017-08-16
      • 1970-01-01
      • 2012-02-18
      相关资源
      最近更新 更多