如何使用 PHP 迭代器仅处理选定的文件夹?

发布于 2024-08-14 17:41:04 字数 1360 浏览 3 评论 0原文

我正在尝试使用 PHP 递归目录迭代器来查找 php 和 html 文件,以便按日期列出这些文件。使用的代码如下:

        $filelist = array();
    $iterator = new RecursiveDirectoryIterator( $this->_jrootpath );
    foreach(new RecursiveIteratorIterator($iterator) as $file) {
        if ( !$file->isDir() ) {
            if ( preg_match( "/.(html|htm|php)$/", $file->getFilename() ) ) {
                $filelist[$file->getPathname()] = $file->getMTime();
            }
        }
    }
    arsort($filelist);
    foreach ($filelist as $key => $val) {
        $resultoutput .= '          <tr>
                                        <td class="filepath">'.$key.'</td>
                                        <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
                                    </tr>';
    }

上面的方法有效,但我需要将迭代限制在某些文件夹中。该脚本将从父文件夹中启动,我希望其中有一些特定的子文件夹,例如“管理员”、“组件”、“模块”、“插件”和“模板”(换句话说,Joomla 安装的标准文件夹)。我还期望父文件夹中有一些文件,例如“index.php”。这些文件和文件夹应该被迭代(坦率地说,写这篇文章时我不确定父文件夹本身是否正在被我的代码迭代!)。但是,父文件夹可能还包含不应迭代的其他子文件夹。这些可以是子域或插件域的子文件夹,例如命名为“mysub”和“myaddon.com”。我想跳过除正常 Joomla 安装文件夹之外的任何文件夹有两个原因。一是我不需要了解其他文件夹中的文件。此外,迭代所有文件夹可能会花费大量时间和资源,以至于我会收到 500 个错误页面。

我的问题是,如何最好地更改我的代码,以确保迭代中排除和包含正确的文件夹?我在网络上看到过检查目录名称的迭代器示例,但这对我没有足够的帮助,因为我只需要检查第二级文件夹名称(意味着仅像parent / secondarylevel / noneedtocheck这样的路径中的最高级别子文件夹) /文件.php)。

I am trying to use the PHP recursive directory iterator to find php and html files in order to list those by date. The code used is as follows:

        $filelist = array();
    $iterator = new RecursiveDirectoryIterator( $this->_jrootpath );
    foreach(new RecursiveIteratorIterator($iterator) as $file) {
        if ( !$file->isDir() ) {
            if ( preg_match( "/.(html|htm|php)$/", $file->getFilename() ) ) {
                $filelist[$file->getPathname()] = $file->getMTime();
            }
        }
    }
    arsort($filelist);
    foreach ($filelist as $key => $val) {
        $resultoutput .= '          <tr>
                                        <td class="filepath">'.$key.'</td>
                                        <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
                                    </tr>';
    }

The above works, but I need to restrict the iteration to certain folders. This script will start in a parent folder where I expect some particular subfolders like 'administrator', 'components', 'modules', 'plugins' and 'templates' (in other words the standard folders of a Joomla installation). I also expect a few files in the parent folder, like 'index.php'. These files and folders should be iterated (frankly, writing this I am not sure if the parent folder itself is being iterated by my code!). However, it is possible that the parent folder also contains other subfolders which should not be iterated. These could be subfolders for subdomains or addon domains, named for example 'mysub' and 'myaddon.com'. There are two reasons why I want to skip any folder except for the normal Joomla installation folders. One is that I don't need to know about files in other folders. Moreover, iterating all folders can take so much time and resources that I get 500 error pages.

My question is how I would best change my code in order to make sure that the right folders are excluded from and included in the iteration? I have seen iterator examples around the web checking the name of a directory, but that does not help me enough, because I only need to check the second level folder names (meaning only the highest level subfolder in a path like parent/secondlevel/noneedtocheck/file.php).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

复古式 2024-08-21 17:41:04

不不!
您想要类似的东西:

<?php
class FilteredRecursiveDirectoryIterator extends FilterIterator
{   
    public function __construct($path)
    {
        parent::__construct(new RecursiveDirectoryIterator($path));
    }
    public function accept()
    {
        if($this->current()->isFile() and in_array($this->getExtention(), array('html', 'php')))
            return true;

        return false;
    }

    private function getExtention()
    {
        return end(explode('.', $this->current()->getFilename()));
    }
}

accept() 方法为您完成所有过滤。我还没有测试过这个,但我确信它很好;)

no no!
YOu want something like:

<?php
class FilteredRecursiveDirectoryIterator extends FilterIterator
{   
    public function __construct($path)
    {
        parent::__construct(new RecursiveDirectoryIterator($path));
    }
    public function accept()
    {
        if($this->current()->isFile() and in_array($this->getExtention(), array('html', 'php')))
            return true;

        return false;
    }

    private function getExtention()
    {
        return end(explode('.', $this->current()->getFilename()));
    }
}

where the accept() method does all the filtering for you. I haven't tested this but I'm sure it good to go ;)

睫毛溺水了 2024-08-21 17:41:04
    $filelist = array();

// 创建一个排除者数组
$excludeDirs= array("/var/www/joomla/admin/");

    $iterator = new RecursiveDirectoryIterator( $this->_jrootpath );
    foreach(new RecursiveIteratorIterator($iterator,RecursiveIteratorIterator::CHILD_FIRST) as $file) {
    if($file->getPathname() == excludeDirs[0])
       continue;
    if ( !$file->isDir() ) {
                    if ( preg_match( "/.(html|htm|php)$/", $file->getFilename() ) ) {
                            $filelist[$file->getPathname()] = $file->getMTime();
                    }
            }
    }
    arsort($filelist);
    foreach ($filelist as $key => $val) {
            $resultoutput .= '<tr>
            <td class="filepath">'.$key.'</td>
           <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
           </tr>';
    }
    $filelist = array();

// make an array of excludedirs
$excludeDirs= array("/var/www/joomla/admin/");

    $iterator = new RecursiveDirectoryIterator( $this->_jrootpath );
    foreach(new RecursiveIteratorIterator($iterator,RecursiveIteratorIterator::CHILD_FIRST) as $file) {
    if($file->getPathname() == excludeDirs[0])
       continue;
    if ( !$file->isDir() ) {
                    if ( preg_match( "/.(html|htm|php)$/", $file->getFilename() ) ) {
                            $filelist[$file->getPathname()] = $file->getMTime();
                    }
            }
    }
    arsort($filelist);
    foreach ($filelist as $key => $val) {
            $resultoutput .= '<tr>
            <td class="filepath">'.$key.'</td>
           <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
           </tr>';
    }
念﹏祤嫣 2024-08-21 17:41:04

我将尝试以下操作:通过将迭代器放入函数中,我可以重复使用它来包含已知文件夹,以构建结果数组。我仍然希望有一天我能找到一种解决方案,可以更优雅地使用 PHP 迭代器,而无需在我的方法中嵌套函数。

    $filelist = array();
    $filelist[$this->_jrootpath.DS.'index.php'] = date("d-m-Y H:i:s",filemtime($this->_jrootpath.DS.'index.php'));
    $filelist[$this->_jrootpath.DS.'index2.php'] = date("d-m-Y H:i:s",filemtime($this->_jrootpath.DS.'index2.php'));
    $joomlafolders = array( $this->_jrootpath.DS.'administrator', $this->_jrootpath.DS.'cache', $this->_jrootpath.DS.'components', $this->_jrootpath.DS.'images', $this->_jrootpath.DS.'includes', $this->_jrootpath.DS.'language', $this->_jrootpath.DS.'libraries', $this->_jrootpath.DS.'logs', $this->_jrootpath.DS.'media', $this->_jrootpath.DS.'modules', $this->_jrootpath.DS.'plugins', $this->_jrootpath.DS.'templates', $this->_jrootpath.DS.'tmp', $this->_jrootpath.DS.'xmlrpc' );
    foreach ( $joomlafolders as $folder ) {
        $iterator = new RecursiveDirectoryIterator( $folder );
        foreach(new RecursiveIteratorIterator($iterator) as $file) {
            if ( !$file->isDir() ) {
                if ( preg_match( "/.(html|htm|php)$/", $file->getFilename() ) ) {
                    $filelist[$file->getPathname()] = $file->getMTime();
                }
            }
        }
    }
    arsort($filelist);
    foreach ($filelist as $key => $val) {
        $resultoutput .= '          <tr>
                                        <td class="filepath">'.$key.'</td>
                                        <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
                                    </tr>';
    }

I am going to try the below: by putting the iterator in a function I can use it repeatedly for known folders to be included in order to build the result array. Still I hope one day I will find a solution that will more elegantly use the PHP iterators without a function nested in my method.

    $filelist = array();
    $filelist[$this->_jrootpath.DS.'index.php'] = date("d-m-Y H:i:s",filemtime($this->_jrootpath.DS.'index.php'));
    $filelist[$this->_jrootpath.DS.'index2.php'] = date("d-m-Y H:i:s",filemtime($this->_jrootpath.DS.'index2.php'));
    $joomlafolders = array( $this->_jrootpath.DS.'administrator', $this->_jrootpath.DS.'cache', $this->_jrootpath.DS.'components', $this->_jrootpath.DS.'images', $this->_jrootpath.DS.'includes', $this->_jrootpath.DS.'language', $this->_jrootpath.DS.'libraries', $this->_jrootpath.DS.'logs', $this->_jrootpath.DS.'media', $this->_jrootpath.DS.'modules', $this->_jrootpath.DS.'plugins', $this->_jrootpath.DS.'templates', $this->_jrootpath.DS.'tmp', $this->_jrootpath.DS.'xmlrpc' );
    foreach ( $joomlafolders as $folder ) {
        $iterator = new RecursiveDirectoryIterator( $folder );
        foreach(new RecursiveIteratorIterator($iterator) as $file) {
            if ( !$file->isDir() ) {
                if ( preg_match( "/.(html|htm|php)$/", $file->getFilename() ) ) {
                    $filelist[$file->getPathname()] = $file->getMTime();
                }
            }
        }
    }
    arsort($filelist);
    foreach ($filelist as $key => $val) {
        $resultoutput .= '          <tr>
                                        <td class="filepath">'.$key.'</td>
                                        <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
                                    </tr>';
    }
如日中天 2024-08-21 17:41:04

您可以尝试使用 RecursiveRegexIterator

编辑这是使用 RecursiveRegexIterator 的示例:

$filelist = array();
$iterator = new RecursiveDirectoryIterator( $this->_jrootpath );
foreach(new RecursiveRegexIterator($iterator, '/\.(html|htm|php)$/') as $file) {
    if ( !$file->isDir() ) {
        $filelist[$file->getPathname()] = $file->getMTime();
    }
}
arsort($filelist);
foreach ($filelist as $key => $val) {
    $resultoutput .= '                      <tr>
                                                                            <td class="filepath">'.$key.'</td>
                                                                            <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
                                                                    </tr>';
}

顺便说一下,看起来 $resultoutput 尚未创建。在这种情况下,您应该将其创建为空字符串...

EDIT2:哎呀,这并不能真正回答您的问题。出于某种原因,我认为这只是关于递归的东西。这只是循环文件的更优雅的解决方案,但它并不能解决您的问题,抱歉。您可能应该将其与其他答案之一结合起来。

You could try using the RecursiveRegexIterator.

EDIT This is your example using the RecursiveRegexIterator:

$filelist = array();
$iterator = new RecursiveDirectoryIterator( $this->_jrootpath );
foreach(new RecursiveRegexIterator($iterator, '/\.(html|htm|php)$/') as $file) {
    if ( !$file->isDir() ) {
        $filelist[$file->getPathname()] = $file->getMTime();
    }
}
arsort($filelist);
foreach ($filelist as $key => $val) {
    $resultoutput .= '                      <tr>
                                                                            <td class="filepath">'.$key.'</td>
                                                                            <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td>
                                                                    </tr>';
}

By the way, it looks like $resultoutput is not created yet. In that case, you should create it as an empty string somewhere...

EDIT2: Oops, this does not really answer your question. For some reason I thought it was only about the recursive stuff. This is just a more elegant solution to loop over the files, but it doesn't solve your problem, sorry. You should probably combine this with one of the other answers.

英雄似剑 2024-08-21 17:41:04

通常,您使用 RecursiveIteratorIterator 来解决 RecursiveDirectoryIterator 中的“递归性”。 RecursiveIteratorIterator 只是一个简单的 Iterator,可以像您可能已经熟悉的任何其他迭代器一样使用。这包括使用 FilterIterator 。在 PHP 5.4 中,它看起来像这样(CallbackIterator是新的)

<?php
$directories = new CallbackIterator(
    new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator('path/to/directory')
    ),
    function($current) {
        return $current->isDir();
    }
);

foreach ($directories as $directory) {
    ...
}

对于 PHP <5.4,您需要自己实现 CallbackIterator

<?php
class CallbackIterator extends FilterIterator
{
    private $callback;

    public function __construct(Traversable $iterator, $callback)
    {
        $this->callback = $callback;
    }

    public function accept()
    {
        return call_user_func($this->callback, $this->current());
    }
}

Usually you use an RecursiveIteratorIteratorto resolve the "recursiveness" in RecursiveDirectoryIterator. A RecursiveIteratorIterator is just a simple Iterator that can be used like any other you might be already familiar with. This includes using FilterIterator with it. In PHP 5.4 it looks like that (CallbackIteratoris new)

<?php
$directories = new CallbackIterator(
    new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator('path/to/directory')
    ),
    function($current) {
        return $current->isDir();
    }
);

foreach ($directories as $directory) {
    ...
}

For PHP <5.4 you need to implement CallbackIteratoryourself

<?php
class CallbackIterator extends FilterIterator
{
    private $callback;

    public function __construct(Traversable $iterator, $callback)
    {
        $this->callback = $callback;
    }

    public function accept()
    {
        return call_user_func($this->callback, $this->current());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文