繁体   English   中英

带MVC的PHP前端控制器

[英]PHP Front Controller with MVC

我正在尝试使用Front Controller Design深入研究MVC。

我想通过使用一行来调用我的整个应用程序,例如在index.php中:

require_once(myclass.php);
$output = new myClass();

我很想摆脱require_once线,但我不知道如何加载我的课程而不包括它?

无论如何,我的主要问题是如何使用一个前端类加载我的各种控制器和模型和视图等。 到目前为止,我想出了:

class myClass
{
    private $name;
    public $root = $_SERVER['DOCUMENT_ROOT'];
    private $route = array("Controller" => "", "Model" => "", "View" => "", "Paremeters" => "");
    function __construct() 
    {   $uri = explode("/",$_SERVER['REQUEST_URI']);
        if(isset($uri[2])) {$this->route['Controller'] = $uri[2];}
        if(isset($uri[3])) {$this->route['Model'] = $uri[3];}
        if(isset($uri[4])) {$this->route['View'] = $uri[4];}
        if(isset($this->route['Controller'])) 
        {
            include($this->root."/".$this->route['Controller'].".php");
        }
    }

}

但它看起来有点令人费解并超过顶部。 此外,一旦我在__construct中包含了新类,我该如何加载它?

我很抱歉缺乏知识,我已经多次用Google搜索,我不断提出相同的页面似乎并没有扩展我对这个问题的了解。

如果您的网址肯定是http://domain.com/[controller]/[action]/ 参数 ,那么您的前端控制器可能如下所示:

<?php
class Application
{
    public function __construct()
    {
        $this->setupAutoloader();
        $this->route();
    }

    private function setupAutoloader()
    {
        // do your autoloading here
    }

    private function route()
    {
        $request = explode('/', trim($_SERVER['REQUEST_URI'], '/'));

        $controller = isset($request[0]) ? ucwords(array_shift($request)) . 'Controller' : 'HomeController';
        $action = isset($request[0]) ? array_shift($request) : 'index';
        $parameters = $request;

        $response = call_user_func_array(array($controller, $action), $parameters);
    }
}

从这里,您可以添加自动加载器实现,对响应执行任何操作,并从index.php中调用它,如下所示:

<?php
require 'path/to/Application.php';

$application = new Application();

不幸的是,如果它存储在文件系统的其他位置,你总是必须包含第一个文件,但是如上所述,你可以自动加载其他类,如库,控制器,模型等。

令我感到惊讶的是,在这两个冗长且信息丰富的先前答案中,没有人愿意以最简单的方式回答你的问题。

你想要__autoload()函数。 您仍然需要在代码中的某个位置定义它,但它可以简单地添加到全局头文件中,然后您不必为每个类定义显式编写包含。

/* auto load model classes */
function __autoload($class_name) {
        $filename = 'class.' . strtolower($class_name) . '.php';
        $file = __SITE_PATH . '/_model/' . $filename;
        if( file_exists($file) == false ) {
                return false;
        }
        require($file);
}

为了在不手动包含类的情况下加载类,您应该查看spl_autoload_register ,它使您能够在应用程序需要时自动加载类。

至于另一个问题,那就完全取决于你的设计。 如果要加载公共“控制器”和“操作”,则应创建可路由文件夹(这意味着只有控制器可以保留的文件夹)并放置所有控制器类,然后创建可路由的操作空间(可路由组)控制器类中的方法,通常是通过定义操作方法以action_为前缀的action_ 完成后,只需像这样创建控制器:

class Blog {
    public function action_posts() { ... };
}

并管理它,以便URL /blog/posts/将调用它。 (它只需要你已经证明擅长的相同的URI操作)。 (请注意,自动加载器应自行处理实际类文件的包含,而不需要加载所有控制器类)。 获得控制器名称和操作后,您只需要以下内容:

if (class_exists($controller)) {
    $app = new $controller;
    if (method_exists($app, $action)) {
        $app->$action(); // also take a look at call_user_func and call_user_func_array
    }
}

您也可以允许参数,但这样做很困难,以便允许这种结果:

class Blog {
    public function action_post($id) { ... };
}

并被/blog/post/14/称为。

处理URI时还要记住,你可能有错误的输入,你应该处理它们,但是如果你已经创建了正确的路由空间,那么你已经完成了一半。

最后,如果你想获得灵感或其他任何东西,只需看看CodeIgniter(这是最容易学习的框架之一)或任何其他框架。

希望它有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM