如何仅基于文件名(PHP)创建类的实例


How to create an instance of a class based solely on a filename (PHP)

我正在制作一个小的PHP MVC框架来取乐。我使用前控制器index.php来路由周围的所有流量,并根据要求呼叫新的控制器。然而,我需要一种方法来创建用户生成的控制器的实例,该实例仅基于控制器的名称(基本上是文件名,即controllers/posts.php)。

有办法做到这一点吗?

有几种方法可以做到这一点。一种方法是建立一个约定,使类的名称基于文件的名称。另一种方法是解析文件中的类名称。你想看一些小代码示例吗?

EDIT:的简单示例

假设我们在某个核心MVC控制器中,并且我们想要加载由第三方用户提供的控制器。你需要做两件事:

  1. 加载带有类定义的文件
  2. 实例化类

假设您有一个约定,如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';
}
?>