PHP:spl_autoload_register + RecursiveDirectoryIterator

时间:2013-09-17 07:18:29

标签: php autoload spl-autoload-register

我想循环主dirs中的所有子目录,例如,我保留所有类,

core/
   model/
       page/
          class_1.php
          class_2.php
       menu/
          class_3.php
       and so on...

所以这是我的自动加载功能,我将它放在init.php中,

function autoload_multiple_directory($class_name){

    // List all the class directories in the array.
    $array_directories = array(
        'core/controller/', 
        'core/model/',
        'core/helper/'
    );

    // When you use namespace in a class, you get something like this when you auto load that class \foo\tidy.
    // So use explode to split the string and then get the last item in the exloded array.
    $parts = explode('\\', $class_name);
    //print_r($parts);

    // Set the class file name.
    $file_name = strtolower(end($parts)).'.php';
    // $file_name = 'class_'.strtolower($class_name).'.php';

    // Loop the array.
    foreach($array_directories as $path_directory){


        $recursive_directory = new RecursiveDirectoryIterator($path_directory);
        foreach (new RecursiveIteratorIterator($recursive_directory) as $filename => $file) {

            if(file_exists(WEBSITE_DOCROOT.$file->getPath().'/'.$file_name)){

                include WEBSITE_DOCROOT.$file->getPath().'/'.$file_name;
            } 

        }


        /* no problem with this, but I cannot loop the sub dirs...
        if(file_exists(WEBSITE_DOCROOT.$path_directory.$file_name)){

            include WEBSITE_DOCROOT.$path_directory.$file_name;
        }
         * 
         */
    }
}


spl_autoload_register('autoload_multiple_directory');

但后来我收到此错误消息,

致命错误:无法在第6行的C:\ wamp \ www \ xxx \ core \ helper \ Common.php中重新声明类Common

我的项目中只有一个Common类。为什么会说不止一次重新声明

但是如果你看一下我注释掉的if(file_exists(WEBSITE_DOCROOT.$path_directory.$file_name)) - 加载类没有问题。这个初始循环的问题是它不会在主目录中循环子目录,例如,core/model/

任何想法为什么以及如何循环主目录的子目录?

修改

问题来自RecursiveDirectoryIterator - 它循环目录并列出所有文件。但我想要的只是子目录。

2 个答案:

答案 0 :(得分:1)

这些文件夹中是否存在多个Common.php文件副本?
由于您的代码在包含类文件后不breakautoloader将继续在文件夹树中寻找具有相同名称的其他文件,并且会导致Fatal error: Cannot redeclare class XXX错误。添加break可以解决问题。

// Loop the array.
$isClassFound = false;
foreach($array_directories as $path_directory){
    $recursive_directory = new RecursiveDirectoryIterator($path_directory);
    foreach (new RecursiveIteratorIterator($recursive_directory) as $filename => $file) {
        if(file_exists(WEBSITE_DOCROOT.$file->getPath().'/'.$file_name)){
            include WEBSITE_DOCROOT.$file->getPath().'/'.$file_name;
            $isClassFound = true;
        }
        if ($isClassFound) break;
    }
    if ($isClassFound) break;
}

但是,autoloader的性质似乎不应该允许任何重复的类文件名。也许你可以写一个名称复制检查器来保证唯一性。

编辑:

我从答案中删除了class_exists()部分,因为使用它并没有多大意义。无论如何,既然你看到了我的答案的那个版本,并且你通过评论问我在哪里放class_exists(),我将重新启动代码示例。您可以在autoloader

的开头添加以下代码
if (class_exists($class_name,false)) // give false to avoid automatic loading
    return;

答案 1 :(得分:-1)

打开开始菜单。在文本框中写下cmd,等待弹出cmd程序,然后按Enter键。

终端窗口打开后,导航到根文件夹,然后对类名称进行递归搜索(通过所有文件和文件夹):

cd C:\wamp\www\xxx
findstr /SNIP /C:"class common" *.php

该课程应该有多个声明。