使用$ _SERVER [' SCRIPT_NAME']来实例化控制器

时间:2013-11-02 04:18:44

标签: php model-view-controller

我在php webapp中使用MVC架构。我的架构非常简单,如果我以这种方式向URL发送请求localhost/Dispatcher.php?class=SampleController&method=sampleMethod,这将实例化控制器SampleController并调用此控制器的方法sampleMethod。顺便说一句,我不能使用.htaccess文件。现在我想摆脱Dispatcher.php,所以我认为如果我将网址的sintax更改为类似localhost/SampleController.php?method=sampleMethod的内容,我就可以实现这一点。为此,我必须使用$_SERVER['SCRIPT_NAME']来获取控制器类名。我的所有控制器都来自Controller。我认为我可以在Controller.php中实例化那里的控制器。所以,我的Controller.php看起来像这样。

<?php
//Enable errors
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);

//Include the controller
$include = explode("/",$_SERVER['SCRIPT_NAME'])[2]; //This return MainController.php
include_once $include;

//Get the method (Like this is an example I don't care the validations)
$method = $_GET['method'];

$class = explode(".",$include)[0]; //Get rid of the *.php extention
$controller = new $class(); 
$controller->$method(); // I get Class 'MainController' not found

include_once 'View.php';
class Controller {
    public $view;
    public function __construct() {
        $this->view = new View();
    }
}

?>

这是我的MainController.php

<?php
include_once 'Controller.php';
include_once 'MainModel.php';
class MainController extends Controller {

    public $model;

    public function __construct() {
        parent::__construct();
        $this->model = new MainModel();
    }

    public function index(){
        $this->view->render('mainView','headerMain','footerMain');

    }
}

?>

我在这里尝试点击此网址MainController.php?method=index

所有名字都没问题,路径也可以。顺便说一句,如果我硬编码路径我得到相同的错误,这可能是一个包含错误?如果我无法在Controller.php中实现这一点,那么在某些地方我可以处理控制器实例化而无需添加另一个.php文件? (我不想回到使用Dispatcher.php

更新 如果我以这种方式更改Controller.php,则有效,但我得到Fatal error: Cannot redeclare class maincontroller in MainController.php on line 9

<?php
include_once 'View.php';

//Enable errors
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);

//Include the controller
$include = explode("/",$_SERVER['SCRIPT_NAME'])[2]; //This return MainController.php

//Get the method (Like this is an example I don't care the validations)
$method = $_GET['method'];
$class = explode(".",$include)[0];

require($include);

$controller = new $class();
$controller->$method();


class Controller {
    public $view;
    public function __construct() {
        $this->view = new View();
    }
}
?>

解决方法

我以这种方式实现了我的目标:

MainController.php

<?php
//Enable errors
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);

include_once 'Controller.php';
include_once 'MainModel.php';
class MainController extends Controller {

    public $model;

    public function __construct() {
        parent::__construct();
        $this->model = new MainModel();
    }

    public function index(){
        $this->view->render('mainView','headerMain','footerMain');

    }
}

require_once("Core.php");

?>

Controller.php这样

<?php
include_once 'View.php';

class Controller {
    public $view;
    public function __construct() {
        $this->view = new View();
    }
}
?>

core.php中

<?php
//Enable errors
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);

//Include the controller
$include = explode("/",$_SERVER['SCRIPT_NAME'])[2]; //This return MainController.php

//Get the method (Like this is an example I don't care the validations)
$method = $_GET['method'];
$class = explode(".",$include)[0];

$controller = new $class();
$controller->$method();

?>

但是这个解决方案仍然不能让我满意,这不是我想要的面向对象的解决方案。在Controller.php

中是不是有办法做到这一点

1 个答案:

答案 0 :(得分:0)

您的问题可能是MainController.php在您的课程定义之前调用了include_once 'Controller.php'。然后,Controller.php将不再包含MainController.php,因为include_once已注意到它已加载。如果您再次使用包含require的{​​{1}},MainController.php中的include_once将不再包含MainController.php,请声明该类并返回{{1} }}。完成Controller.php后,它将返回原始Controller.php,但无法再次声明该类。

您可以在Controller.php的末尾使用MainController.phpdie(),但我更愿意声明一个函数,让我们说exit(),它可以完成所有这些工作初始化后,将其称为Controller.php的最后一行。

<强> Controller.php这样

Process()

<强> MainController.php

MainController.php