【问题标题】:Best way to parse request into Controller / Function / Parameters将请求解析为控制器/函数/参数的最佳方法
【发布时间】:2017-11-10 03:01:18
【问题描述】:

我开始尝试自己的 MVC。

我的目标只是实现控制器模型和视图并将它们关联起来,但不幸的是,它朝着(小)框架方向发展。

我在根文件夹中有一个基本的 index.php,它负责路由。 (确定应该创建哪个控制器,将在新创建的控制器实例上调用哪个函数等)

我直接从 url 解析控制器、函数和变量(就像 codeigniter 正在做的那样) ex :http://baseurl/index.php{router} /User{controller}/get{function to be called}/1{variable-0}/desc{variable-1} 而不是使用 get 方法来识别它们(如 ?c=mainController&f=function_to_be_call)。

我的问题是(基于我在做什么),是否有另一种(更好的方法)来实现相同的结果?

编辑:
示例请求:http://localhost:8080/ut/User/getUser/1

输出:array(3) { ["controller"]=> string(4) "User" ["function"]=> string(7) "getUser" ["variables"]=> array(1) { [2] => 字符串(1) "1" } }

感谢您的关注。

<?php

namespace System;

class UrlParser
{
public static function parseRequest(string $url):?array
{
    //default destination if nothing matches
    $destination = '404';//self::$routes['index'];

    //the order: controller to be loaded, function to be called and parameters etc...
    $hierarchical_call = array();
    //remove www : [I know its not generic]
    //TODO: check base url if it contains www, don't remove www
    $url = str_replace('www', '', $url);
    // check for a trailer slash, if not add it
    $url = substr($url, strlen($url) - 1, 1) === '/' ? $url : $url . '/';

    // split url into base url and rest
    $url_parts = explode(baseurl, $url);
    //url has more content
    if (count($url_parts) > 1) {
        $rest_url = $url_parts[1];

        /*add leading slash for regex, it is easier to get the string between two slashed insteadof [A-Z]*/
        $rest_url = substr($rest_url, 0, 1) === '/' ? $rest_url : '/' . $rest_url;

        /*
         * use regex to get the first part which is between / and /
         * if it is index.php than check if url parts has any other request
         */
        $pattern = '/[a-zA-Z0-9_\.]+/';
        preg_match_all($pattern, $rest_url, $request_parts, PREG_SET_ORDER);
        /*
         * PREG_PATTERN_ORDER
         * Orders results so that $matches[0] is an array of full pattern matches,
         * $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on.
         */
        for ($i = 0; $i < count($request_parts); $i += 1) {
            //the requested file is determined add the remaining parts to it
            if (strlen($request_parts[$i][0]) > 0 && $request_parts[$i][0] !== 'index.php') {
                $hierarchical_call[] = $request_parts[$i][0];
            }
        }
    }
    return $hierarchical_call;
  }
}

【问题讨论】:

    标签: php url-routing


    【解决方案1】:

    Php 有内置函数 - parse_url.

    $url = 'http://localhost:8080/ut/User/getUser/1';
    $parsed = parse_url($url); 
    var_dump($parsed);
    
    
    
    array(4) { 
       ["scheme"]=> string(4) "http" 
       ["host"]=> string(9) "localhost"
       ["port"]=> int(8080)
       ["path"]=> string(18) "/ut/User/getUser/1"
    }
    

    之后explode路径:

    $route = explode("/", $parsed['path']);
    var_dump($route);
    
    
    
    array(5) {
        [0]=> string(0) "" 
        [1]=> string(2) "ut"
        [2]=> string(4) "User"
        [3]=> string(7) "getUser"
        [4]=> string(1) "1"
    }
    

    【讨论】:

    • 感谢您的回答,但在我的情况下它没有帮助(完全解决问题)。网址 :localhost:8080/ut/User/getUser/1 输出 :array(4) { ["scheme"]=> string(4) "http" ["host"]=> string(9) "localhost" ["port"]=> int(8080 ) ["path"]=> string(18) "/ut/User/getUser/1" } 但我可以将它用于解析的第一部分(从 reuqest 路径中删除基本 url。
    • 完成,我已将示例请求和当前输出添加到问题中
    【解决方案2】:

    首先,你不需要解析完整的URL,因为你可以检索到用户的调用
    $_SERVER['REQUEST_URI'] ...但我想这不是那么优雅。

    至于拆分该 URI 路径,您实际上应该使用正则表达式。在您的具体示例中,正则表达式为:
    '#^/ut/(?P&lt;controller&gt;[\w]+)/(?P&lt;method&gt;[\w]+)/(?P&lt;id&gt;[\d]+)$#i'

    现场样例:here

    您可以阅读更多关于如何制作路由代码 here 的信息,但除非您将其作为学习经验,否则您可能应该改用现有的库,例如 FastRoute 或 Symfony 的 standalone router

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-24
      • 1970-01-01
      • 2013-10-09
      • 1970-01-01
      相关资源
      最近更新 更多