【问题标题】:How to create an instance of a class based solely on a filename (PHP)如何仅基于文件名(PHP)创建类的实例
【发布时间】:2012-04-12 14:53:39
【问题描述】:

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

有没有办法做到这一点?

【问题讨论】:

    标签: php model-view-controller oop class


    【解决方案1】:

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

    编辑:简单示例

    假设我们在某个核心 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();
    

    希望这足以让您滚动;如果您需要更多,请告诉我。

    【讨论】:

    • 如果您不介意,我很乐意看到一些示例。我喜欢约定的想法——我认为 CodeIgniter 使用了它。但是,我如何能够在另一个目录中创建类/文件的新实例?
    • +1,这个实现很震撼。它有助于使您的文件井井有条并且易于查找。此外,它还避免了像冠军一样的命名空间冲突。
    • 看起来很棒!谢谢@quickshiftin
    【解决方案2】:

    是的,在您的前端控制器或路由器类中检查控制器文件是否存在后,您可以调用它: 以下是我从路由器类中提取的一些方法,它们可能对您有所帮助,它是一个示例,但如果您遵循,您可以看到如何加载类以及如何调用方法或操作:

    <?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';
    }
    ?> 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      • 1970-01-01
      相关资源
      最近更新 更多