Php 在特定文件夹HMVC中自动加载模型类的最佳方法

Php 在特定文件夹HMVC中自动加载模型类的最佳方法,php,oop,autoload,hmvc,Php,Oop,Autoload,Hmvc,我目前正在编写自己的PHP框架,作为使用HMVC设计模式的学习练习。它都可以工作:),但我已经读过很多次,在PHP代码中引用静态类是一个坏习惯,这正是我在自动加载函数中所做的: function __autoload($className) { $path = SERVER_ROOT . DS . 'applications' . DS . Dispatcher::getApplicationName() . DS . 'models' . DS . 'class.' . strtolo

我目前正在编写自己的PHP框架,作为使用HMVC设计模式的学习练习。它都可以工作:),但我已经读过很多次,在PHP代码中引用静态类是一个坏习惯,这正是我在自动加载函数中所做的:

function __autoload($className) {
    $path = SERVER_ROOT . DS . 'applications' . DS . Dispatcher::getApplicationName() . DS . 'models' . DS . 'class.' . strtolower($className) . '.php';

    if (file_exists($path)) {
        require_once($path);
    } else {
        throw new Exception('Can\'t find a model at "' . $path . '".');
    }
}
如您所见,我使用静态调用
Dispatcher::getApplicationName()
获取当前应用程序,这对许多人来说是不好的,因为它引入了依赖项。我还可以使用
debug\u backtrace()
获取applicationName,因为启动模型的类包含applicationName作为属性。这是更好的选择,还是有其他我没有想到的选择

谢谢

编辑:忘记提到上面的代码还有另一个问题:控制器的应用程序并不总是等于调度器的应用程序,因为我使用的是HMVC设计模式(因此控制器被称为控制器内部)。只能使用
debug\u backtrace
修复此问题

编辑:我现在使用的不是
Request::getCurrentApplicationName()
,而是
Dispatcher::getApplicationName()。它现在再次工作,因为我的请求类保存了所有应用程序。这更好,还是有更好的方法

<?php

class Request {
    private static $_controllers = array();
    private static $_applicationsNames = array();

    public static function _getCurrentApplicationName() {
        return end(self::$_applicationsNames);
    }

    public static function _load($applicationName, $controllerName, $methodName) {
        // Add the application the the array (for autoloading).
        self::$_applicationsNames[] = $applicationName;

        // Check if the controller has already been instantiated.
        if (!isset(self::$_controllers[$applicationName . DS . $controllerName])) {
            require_once(APPLICATIONS_ROOT . DS . $applicationName . DS . 'controllers' . DS . 'class.' . $controllerName . '.php');
            self::$_controllers[$applicationName . DS . $controllerName] = new $controllerName($applicationName);
        }

        // Get the user arguments.
        $arguments = array_slice(func_get_args(), 3);

        // Call the method.
        $result = call_user_func_array(array(self::$_controllers[$applicationName . DS . $controllerName], $methodName), $arguments);

        // Remove the last value from the applications array.
        array_pop(self::$_applicationsNames);
    }
}

<代码> 我会考虑在任何文件引导应用程序中设置<代码>应用程序>根>代码>定义。这将是一件非常有用的事情,它可以一直使用,而不仅仅是在
\uuu autoload
中,您不能在启动期间设置autoload类的静态成员,其中包含所有必要的信息吗

debug_backtrace()不能是可靠的信息源。如果有人想使用你的库和你的自动加载器,但没有一个起始层,该怎么办?有可能吗

类/函数使用的所有数据都应放在该类中或作为函数的参数。因为autoloader可以是任何回调,所以您可以执行以下操作:

class FrameworkAutoloader
{
    public $appName;
    public $path;

    public function setAppName($name) { $this->appName = $name; }
    public function setPath($path) { $this->path= $path; }


    function __autoload($className) {
        $path = $this->path. DS . 'applications' . DS . $this->appName . DS . 'models' . DS . 'class.' . strtolower($className) . '.php';

        if (file_exists($path)) {
             require_once($path);
        } else {
             throw new Exception('Can\'t find a model at "' . $path . '".');
        }
    }
}

$autoloader = new FrameworkAutoloader();
$autoloader->setAppName('asd'); //you can also apply those within constructor, but leave setters
$autoloader->setPath('asd');
spl_autoload_register(array($autoloader, '__autoload'));
就这些。您将能够动态地设置path和appname—只需使用setter更改对象的变量即可


我们为什么要这样做?在这段代码中,没有“魔法”。您可以使用PHPDOC为每个函数编写文档,用户将知道所有参数的来源。另一个优点是,我可以在任何地方使用此代码,我不需要知道,该类使用Dispatcher::getApplicationName()

这意味着我必须更改请求类中每个请求的值。这真的比我在开始文章中编辑的代码好吗?我相信这可以通过为每个应用程序创建单独的自动加载器来解决。创建注册机制,该机制将调用类似MyApplication::install()的内容。这样的解决方案将为您的代码提供更多的模块化。这样做的另一个优点是可以同时从不同的应用程序加载类(尽管这会带来一些性能问题,所以您需要决定哪一个更重要)。例如,PollApp在poll的第一个实例中加载PollTextModel,然后NewsApp加载一些类,最后PollApp加载第二个实例的PollDbModel。谢谢您的回答。这正是我几个小时前的想法。因为我使用HMVC模式,所以每个控制器都是通过我的
Request
类实例化的。因此,我添加了一个控制器方法作为autoloader,并在请求完成时将其删除。这真的很有效。谢谢你的帮助!我不知道HMVC是如何工作的,但你甚至可以跳过删除autoloader。我不能这样做,因为
应用程序的根
定义在我的
请求
类中的每个请求上都会更改。应用程序可以从不同的应用程序加载控制器,然后应用程序就不再正确。你能想出别的办法吗?