将请求解析为Controller / Function / Parameters

时间:2017-11-09 10:40:44

标签: php url-routing

我开始尝试使用自己的MVC。

我的目标只是实现控制器模型和视图并将它们联系起来,但不幸的是,它在(小)框架方向上进行。

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

我直接从url解析控制器,函数和变量(就像codeigniter正在做的那样) 例如: 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_called)。

我的问题是(基于我正在做的事情),还有另一种(更好的方法)来实现相同的结果吗?

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

输出:array(3){[" controller"] => string(4)" User" ["功能"] => string(7)" getUser" ["变量"] => 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;
  }
}

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

实时样本:here

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