是否有一种快速有效的方法来扫描目录并根据找到的文件生成标记?

时间:2011-04-16 10:23:39

标签: php smarty markup

我编写了这段代码,它的作用是根据从数据库中提取的信息设置路径变量。然后它搜索目录并将我想要插入的文件拉出到我的页面中。

我使用Smarty模板引擎,我的问题是,即使这样可以达到我想要的程度。它运行速度非常慢,需要一段时间来扫描目录,然后在整个页面加载之前拉出文件并制作标记。

// Load variables based on if the user has a custom theme applied or a default one
$theme_name = $default->get_theme('theme_dir_name', 'dash');
if($users->get_settings('theme_is_custom', $auth->session->get('user_id')) == 1)
{
    $css_path = "/".$auth->session->get("user_name")."/css";
    $theme_dir  = dirname(__FILE__) . "/assets/users/".$users->get_user_id($_GET['user'])."/themes/".$theme_name."/tpl/";
    $s->assign("css_dir", $css_path."/".$theme_name);
    $s->assign("js_dir" , "/".$_GET['user']."/js/".$theme_name);
}else{
    $css_path = "/css";
    $theme_dir  = dirname(__FILE__) . "/assets/default/themes/".$theme_name."/tpl/";
    $s->assign("css_dir", $css_path."/".$theme_name);
    $s->assign("js_dir" , "/js/".$theme_name);
}
// Load modules
foreach($users->get_active_module($auth->session->get('user_id')) as $m)
{
    if(@$m['module_is_custom'] == 1)
    {
        $path = "/".$auth->session->get("user_id")."/modules/".$m['module_folder_name']."/index.php";
        $dir = "/".$auth->session->get("user_id")."/modules/".$m['module_folder_name'];
    }else{
        $path = dirname(__FILE__)."/assets/default/modules/".$m['module_folder_name']."/index.php";
        $dir = dirname(__FILE__)."/assets/default/modules/".$m['module_folder_name'];
        $js = "/modules/default/".$m['module_folder_name']."/js/";
        $css = "/modules/default/".$m['module_folder_name']."/css/";
    }
    $css_module = "";
    $js_module = "";
    $module = $s->fetch($path);
    if($handle = opendir($dir."/css/"))
    {
        while(false !== ($file = readdir($handle)))
        {
            if($file != "." && $file != ".."){
                $css_module .= '<link rel="stylesheet" href="'.$css.$file.'" />';
            }
        }
        closedir($handle);
    }
    if($handle = opendir($dir."/js/"))
    {
        while(false !== ($file = readdir($handle)))
        {
            if($file != "." && $file != "..")
            {
                $js_module .= '<script type="text/javascript" src="'.$js.$file.'"></script>';
            }
        }
        closedir($handle);
    }
    $s->assign($m['module_folder_name']."_module", $css_module."\n".$js_module."\n".$module);
}

编辑:

function getFileList($dir)
    {
        $retval = array();
        if(substr($dir, -1) != "/")
            $dir .= "/";
        $d = @dir($dir) or die("getFileList: Failed opening directory $dir for reading");
        while(false !== ($entry = $d->read()))
        {
            if($entry[0] == ".")
                continue;
            if(is_dir("$dir$entry"))
            {
                $retval[] = array( "name" => "$dir$entry/", "type" => filetype("$dir$entry"), "size" => 0, "lastmod" => filemtime("$dir$entry") );
            }elseif(is_readable("$dir$entry")){
                $retval[] = array( "name" => "$dir$entry", "type" => mime_content_type("$dir$entry"), "size" => filesize("$dir$entry"), "lastmod" => filemtime("$dir$entry") );
            }
            echo basename("$dir$entry")."<br />";
        }
        $d->close(); return $retval;
    }

2 个答案:

答案 0 :(得分:0)

如果您使用的是PHP 5.3或更高版本,我建议您使用SPL FilesystemIterator作为优雅解决方案。

这种方法的一个好处是你可以通过将迭代器交换到RecursiveIteratorIteratorRecursiveDirectoryIterator来进行递归。

您还可以使用fileinfo类而不是已弃用的mime_content_type()

以下是Oliver's answer的替代品:

function getFileList($dir, $recursive = false)
{
    $finfo = new finfo(FILEINFO_MIME);
    $retval = array();

    if ($recursive)
    {
        // Note: If RecursiveIteratorIterator::SELF_FIRST is removed it will use the default
        //       RecursiveIteratorIterator::LEAVES_ONLY and therefore ignore directories.
        $iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), 
                                                    RecursiveIteratorIterator::SELF_FIRST);
    }
    else
    {
        $iter = new FilesystemIterator($dir);
    }

    foreach ($iter as $path => $info)
    {
        $filename = $info->getFilename();

        if ("." === $filename[0])
        {
            // ignore hidden files on unix for compatability with the Oliver's function
            // note that the default constructor flag FilesystemIterator::SKIP_DOTS will have skipped the . and .. files anyway.
            continue;
        }

        $val = array("name" => $path, 
                     "type" => $info->getType(), 
                     "size" => $info->getSize(), 
                     "lastmod" => $info->getMTime());

        if ($info->isFile())
        {
            $fulltype = $finfo->file($path);
            // $finfo->file() returns something like "application/octet-stream; charset=binary"
            // the first part matches what mime_content_type() returns, ignore the rest for compatability with Oliver's function
            $ftypeparts = explode(";", $fulltype, 2);
            $val ["type"] = $ftypeparts[0];
        }

        $retval[] = $val;
    }

    return $retval;
}
PHP 5.2或更高版本上的

SPL DirectoryIterator也会执行大部分操作,但您需要使用mime_content_type()

答案 1 :(得分:-1)

使用此功能,我自己编写并在多个项目中使用它

function getFileList($dir) { 
    $retval = array(); 
    if(substr($dir, -1) != "/") $dir .= "/"; 
    $d = @dir($dir) or die("getFileList: Failed opening directory $dir for reading"); 
    while(false !== ($entry = $d->read())) { 
        if($entry[0] == ".") continue; 
        if(is_dir("$dir$entry")) { 
            $retval[] = array( "name" => "$dir$entry/", "type" => filetype("$dir$entry"), "size" => 0, "lastmod" => filemtime("$dir$entry") ); 
        } elseif(is_readable("$dir$entry")) { 
            $retval[] = array( "name" => "$dir$entry", "type" => mime_content_type("$dir$entry"), "size" => filesize("$dir$entry"), "lastmod" => filemtime("$dir$entry") ); 
        } 
    } 
    $d->close(); 
    return $retval; 
}

请注意我上面发布的函数...除此之外,首先加载您将在数组中使用的所有数据,然后在收集所有数据后一次性处理标记。