PHP MVC类根据url决定执行哪种方法

时间:2013-04-08 11:37:05

标签: php url-routing

我正在尝试学习MVC,我想在网址为www.example.com/store时显示商店页面,而另一个购物车页面是网址www.example.com/store/cart。两种方法都在一个类中:

class store extends controller {
    function __construct() {
        parent::__construct ();
    }

    function Store() { //this should display the store page
        $this->view->render ( "store" );
    }

    function cart() { //this should display the cart page
        $this->view->render ( "store", "cart.php" );
    }
}

方法$this->view->render()包含带有html代码的页面。 如何根据网址决定执行哪种方法?

3 个答案:

答案 0 :(得分:9)

我可以看到你正在尝试编写自己的MVC,所以我会尝试解释你在做这件事时应该注意的事情。

在编写MVC时,您要做的第一件事就是使用Front Controller模式。 这意味着每个HTTP请求都将通过一个文件index.php。 这将帮助您在一个文件中配置您的应用程序。你可以这样做,只需要打开你的说法:

www.example.com/index.php/controller/method/param1/param2

或者您可以强制用户使用.htaccess文件浏览index.php。 供参考检查其他框架,如Codeigniter和CakePHP,看看他们如何使用.htaccess文件。

当您在前端控制器文件中时,您应该考虑将HTTP请求路由到适当的控制器/方法。有很多方法可以实现这一点,并由您决定最佳方法。

无论如何,你需要Router类来分析你的URL,并从URL中提取你需要的Controller / Method / Params。然后,当您知道需要调用的Controller / Method时,您需要Dispatcher类来实例化Controller,并调用您需要的Method。您还应该考虑要传递给方法的Params,以便在那里使用它们。

解决这个问题的最简单方法是使用查询字符串。

所以假设你有这样的网址:

http://localhost/test/index.php?controller=home&method=welcome

您可以轻松获取控制器和方法名称。

现在你可以这样做:

// Get controller and method names
$controller = $_GET['controller'];
$method = $_GET['method'];

// Instantiate controller object
$app = new $controller();

// Call method on you controller object
call_user_func_array(array($app, $method));

这就像你可以做的最简单的事情。 一旦掌握了这一点,编写你的Router类,它看起来像这样:

http://localhost/test/index.php/controller/method/param1/param2

无论如何你需要这些课程:

前端控制器所以每个请求都通过一个文件,这是你引导你的应用程序,注册类自动加载,配置一切等... 这不是一个类,而是一个带有过程代码的文件,可以启动所有内容。

路由器,它将分析网址并返回您想要传递给调用方法的Controller,Method和Params。

将实例化Controller并调用Method将Params传递给Method的

Dispatcher

然后所有控制权交给你的系统用户,然后你在你的控制器/方法中做你的魔法。

在调度请求时,您也可以使用:

call_user_func_array(array($app, $method), $params);

这样你就可以将$ params传递给$ method,所以你可以在你的方法中使用$ params。

另外,查看Reflection类,这可以帮助您分析是否存在要调用的方法,如果不存在,则应该调用HTTP 404等...

对你的问题没有简单的回答,但我希望这会有所帮助, 有趣的建立你的系统,只是改进,直到你完美:)

答案 1 :(得分:2)

您需要有一个单独的Router类来执行对控制器的路由请求。我建议查看/复制Symfony's Router

答案 2 :(得分:1)

我曾经做过这样的事情来做家酿方法。 使用.htaccess(apache)/ Web.config(iis)将所有请求重定向到以下脚本。

// include callable controllers here
$partsA = explode("?", $_SERVER['REQUEST_URI']); // split querystring
$partsB = explode("/", $partsA[0]); // get url parts
if (count($partsB) < 2)
    die("missing controller in url");
elseif (count($partsB) < 3)
    die("missing action in url");
$className = $partsB[1];
$methodName = $partsB[2];
if (class_exists($className))
    if (!is_subclass_of($className, "controller"))
        die(htmlspecialchars("Class $className doesn't extend controller")); // prevents use of unauthorized classes
    else
        $controller = new $className();
else
    die(htmlspecialchars("Class $className doesn't exist"));

if (!method_exists($controller, $methodName))
    die(htmlspecialchars("Method $methodName doesn't exist"));
else
    $controller->$methodName();
相关问题