CodeIgniter为什么不使用`__autoload()`(或`spl_autoload_register`)

时间:2011-05-15 02:24:55

标签: php oop codeigniter singleton autoload

我最近一直在研究如何最好地组织我的图书馆/课程,我还没有想出一个满意的解决方案。写$xyz = new XyzImplementation()而不是$xyz = $this->load->library('xyz_implementation')只会更加清晰。而且只有多个实例才会变得更糟,它似乎非常适合将库/模型用作单例。

为什么CodeIgniter本身不使用spl_autoload_register__autoload()?我知道CI知道它的类文件在哪里,所以每次实例化类时都不一定需要查看。这只是速度吗?和/或保持轻量级?如果是这种情况,那么我想知道最好使用哪种方法来赋予CI这一功能,即$xyz = new XyzImplementation()

我已经尝试了HMVC,但不喜欢它基本上废弃核心CI_Loader并重新实现每个功能的事实。我不知道如果核心方法的内容要改变会发生什么......我猜任何使用HMVC的人都必须等待它被修补(或者在github上自己修补)

我今晚想出了自己的解决方案,但我不确定它的效率是多少。它基本上使用directory_mapXyzImplementation.php以下的任何地方查找相应名称的类(例如APPPATH)。听起来很可怕,对吗?一旦找到XyzImplementation.php一次,它的位置就会被缓存在一个文件中,下次只是查找一下,所以一旦网站/应用程序经过一些测试,没有理由为什么每个实例都不会看起来 - 起来。

这听起来像是一个不错的解决方案吗?假设find_class_path使用递归目录查找返回找到的类文件的完整相对路径。

// ignore system classes
if('CI' === substr($name, 0, 2) || 'MY' === substr($name, 0, 2))
{
    return;
}

// read cache
$cache = array();
$cache_file = APPPATH.'cache/abracadabra.php';
$class_in_cache = false;
if(file_exists($cache_file))
{
    $cache_contents = file_get_contents($cache_file);
    if(!empty($cache_contents))
    {            
        $cache = unserialize($cache_contents);
        if(array_key_exists($name, $cache))
        {
            $class_in_cache = true;
            include_once($cache[$name]);
        }
    }
}

// class not in cache, find it in application
if(!$class_in_cache)
{
    // TODO be more restrictive than APPPATH
    $class_path = find_class_path($name, APPPATH);
    // TODO handle case where a class isn't found
    $cache[$name] = $class_path;
    file_put_contents($cache_file, serialize($cache)); // add to cache
    include_once $class_path;
}

// instantiate
if(class_exists($name)) // so as to not instantiate interfaces
{
    return new $name;
}

1 个答案:

答案 0 :(得分:2)

不是CodeIgniter的开发者,我不能说他们为什么不使用__autoloadspl_autoload_register。但是,我可以想到 I 可能没有的几个原因:

  • 某些操作码缓存不支持自动加载。对于将在生产中的各种服务器上使用的产品,这将是一个疏远的错误,并可能导致实质性的性能损失,其中,速度是CodeIgniter的主要吸引力。

  • 使用$ this-> load->库('authentication')语法可以更有效地区分正在加载的内容,无论是帮助程序,库,模型等,我认为使您的代码更易于阅读。

关于自动加载类的实现,假设所有使用过的类都缓存在缓存文件中。您正在为执行的每个类实例添加额外的IO请求和不必要的内存使用量。如果您认为您的应用程序将达到企业级别,那就是可以回过头来获得这种开销。在你变大之前考虑这些事情是很好的,它会在以后为你节省心痛和金钱。

说实话,我发现CodeIgniter处理类实例化的方式没什么问题。我同意使用CodeIgniter加载器更适合单例式使用,但是如果你需要实例化一个类的实例,比如一个person对象,那么为什么不像普通的PHP类一样包含它呢?事实上,如果您因为与模型有关的原因进行实例化,为什么不使用一个优秀的ORM框架呢?