Существует ли быстрый и эффективный способ сканирования каталога и создания разметки на основе найденных файлов? - PullRequest
0 голосов
/ 16 апреля 2011

Я написал этот блок кода и установил переменные пути в зависимости от информации, извлеченной из базы данных. Затем он просматривает каталоги и извлекает файлы, которые я хочу вставить на свою страницу.

Я использую шаблонизатор 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);
}

EDIT:

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 голосов
/ 16 апреля 2011

Если вы используете PHP 5.3 или более позднюю версию, я бы предложил использовать SPL FilesystemIterator в качестве элегантного решения для этого.

Одна из приятных сторон этого подхода заключается в том, что вы можете сделать его рекурсивным, переключив итератор на RecursiveIteratorIterator и RecursiveDirectoryIterator.

Вы также можете использовать класс fileinfo вместо устаревшего mime_content_type().

Вот замена для Ответ Оливера :

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

SPL DirectoryIterator в PHP 5.2 или более поздней версии также сделает большую часть этого, хотя вам нужно будет использовать mime_content_type().

0 голосов
/ 16 апреля 2011

используйте эту функцию, я написал ее сам и использую в нескольких проектах

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

Обратите внимание на функцию, которую я написал выше ... кроме этого, сначала загрузите все данные, которые вы собираетесь использовать в массивах, а затем обработайте разметку за один раз после того, как вы собрали все данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...