我正在制作一个小的PHP MVC框架来取乐。我使用前控制器index.php
来路由周围的所有流量,并根据要求呼叫新的控制器。然而,我需要一种方法来创建用户生成的控制器的实例,该实例仅基于控制器的名称(基本上是文件名,即controllers/posts.php
)。
有办法做到这一点吗?
有几种方法可以做到这一点。一种方法是建立一个约定,使类的名称基于文件的名称。另一种方法是解析文件中的类名称。你想看一些小代码示例吗?
EDIT:的简单示例
假设我们在某个核心MVC控制器中,并且我们想要加载由第三方用户提供的控制器。你需要做两件事:
- 加载带有类定义的文件
- 实例化类
假设您有一个约定,如Zend,其中类名映射到文件系统,因此控制器可能是
MyProject/Controller/Login.php
用于登录控制器的路径,相对于项目的根。根据Zend约定,类的名称将是MyProject_Controller_Login
。如果你想实例化这个类,你所要做的就是:
// load class
require_once 'MyProject/Controller/Login.php';
// instantiate class
$oUserController = new MyProject_Controller_Login();
如果需要根据运行时数据实例化类,可以使用一个包含类名称的变量来实现,因此
$sUserController = 'MyProject_Controller_Login';
$oUserController = new $sUserController();
希望这足以让你开始行动;如果你需要更多,请告诉我。
是的,在前端控制器或路由器类中检查控制器文件是否存在后,您可以调用它:以下是我从路由器类中提取的几个方法,这些方法可能会对您有所帮助,这是一个示例,但如果您遵循,您可以看到如何加载类,以及如何调用方法或操作:
<?php
/**
* Load Class based on controller or action
*/
public function load_controller(){
/*Get the route*/
$this->getController();
/*Assign front controller to handle routes that dont have core controller
eg ./core/controllers/($this->file.Controller).php
*/
if (is_readable($this->file) === false){
$this->file = $this->path.'/frontController.php';
$this->subaction = $this->action;
$this->action = $this->controller;
$this->controller = 'front';
}
/*Include core controller file*/
include($this->file);
/*Create controllers class instance & inject registry*/
$className = $this->controller.'Controller';
$controller = new $className($this->registry);
/*Check the action method is callable within the class*/
if (is_callable(array($controller, $this->action)) === false){
//index() method because not found method
$action = 'index';
}else{
//action() method is callable
$action = $this->action;
}
/*Run the action method*/
$controller->$action();
}
private function getController() {
$route = (!isset($_GET['route']))?'':$this->registry->function->cleanURL($_GET['route']);
/*Split the parts of the route*/
$parts = explode('/', $route);
$this->request = $route;
$corefolders=array('core','templates');
if (empty($route) || in_array($parts[0],$corefolders)){
$route = 'index';
}else{
//Assign which controller class
$this->controller = $parts[0];
if(isset($parts[1])){
/* Site.com/action */
$this->action = $parts[1];
}
if(isset($parts[2])){
/* Site.com/action/subaction */
$this->subaction = $parts[2];
}
}
/*Set controller*/
if (empty($this->controller)){$this->controller = 'index';}
/*Set action*/
if (empty($this->action)){$this->action = 'index';}
/*Set the file path*/
$this->file = $this->path.'/'.$this->controller.'Controller.php';
}
?>