There is no problem not worth solving, and no technology not worth learning!

Filter out unwanted file implementations in a directory based on SPL iterator

运行时报错

1. In a template directory, because there are some files that need to be ignored, it is also written into the table, so it needs to be filtered out. Reference: In Laravle 6, togos/phpgitignore, implementation for parsing and applying .gitignore class rules

2. The current code implementation


    private \RecursiveIteratorIterator $iterator;

    private $themeLocation;

    public function __construct($themeLocation)
    {
        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($themeLocation, \FilesystemIterator::SKIP_DOTS)
        );
        $this->iterator = $iterator;
        $this->themeLocation = $themeLocation;
    }


3. The result is for example: the file starting with node_modules is written to the database. as shown in Figure 1

导致的结果就是例如:node_modules 开头的文件被写入至数据库中
Figure 1

4. It is expected to be realized through the RecursiveFilterIterator class to avoid writing ignore files to the database. This abstract iterator filters out unwanted values for RecursiveIterator. This type should be extended to implement custom filters. RecursiveFilterIterator::accept() must be implemented in subclasses. Reference:https://www.php.net/manual/zh/class.recursivefilteriterator.php. Recursive directory/file listing, filters “.svn”.

5. Create a new ThemeViewIgnoRefinder.php to get an array of ignore files. IncludeDirectories is set to true to include directories.


<?php

namespace Modules\ThemeStoreDB\Installer;

use TOGoS_GitIgnore_FileFinder;
use TOGoS_GitIgnore_Ruleset;

class ThemeViewIgnoreFinder
{
    const THEMEIGNORE = '.themeignore'; // 主题忽略配置文件

    public $ignoreResults;

    private $themeLocation;

    public function __construct($themeLocation)
    {
        $this->themeLocation = $themeLocation;
        $this->ignoreResults = [];
    }

    /**
     * 添加忽略文件
     * @param $f
     * @param $result
     * @return void
     */
    public function addIgnoreResult($f, $result) {
        $this->ignoreResults[$f] = $result;
    }

    /**
     * 查找忽略文件
     * @return array
     */
    public function findIgnoreFiles() {
        $rulesContent = file_get_contents($this->themeLocation . DIRECTORY_SEPARATOR . self::THEMEIGNORE);
        $finder = new TOGoS_GitIgnore_FileFinder([
            'ruleset' => TOGoS_GitIgnore_Ruleset::loadFromString($rulesContent),
            'invertRulesetResult' => false,
            'defaultResult' => false,
            'includeDirectories' => true,
            'callback' => [$this, 'addIgnoreResult']
        ]);

        $finder->findFiles($this->themeLocation);

        return $this->ignoreResults;
    }

}



6. Create a new ThemeViewRecursiveFilterIterator.php to implement a custom filter


<?php

namespace Modules\ThemeStoreDB\Installer;

class ThemeViewRecursiveFilterIterator extends \RecursiveFilterIterator
{
    protected $filters;

    public function __construct(\RecursiveIterator $iterator, $ignoreResults) {

        $this->filters = $ignoreResults;
        parent::__construct($iterator);
    }

    public function accept() {

        $accept = true;

        if (isset($this->filters[$this->current()->getFilename()])) {
            $accept = !$this->filters[$this->current()->getFilename()];
        }

        return $accept;
    }


}



7. Edit the SPL iterator code implementation


    private \RecursiveIteratorIterator $iterator;

    private $themeLocation;

    public function __construct($themeLocation)
    {
        $dirIterator = new \RecursiveDirectoryIterator($themeLocation, \FilesystemIterator::SKIP_DOTS);
        $themeViewIgnoreFinder = new ThemeViewIgnoreFinder($themeLocation);
        $filterIterator = new ThemeViewRecursiveFilterIterator($dirIterator, $themeViewIgnoreFinder->findIgnoreFiles());
        $iterator = new \RecursiveIteratorIterator($filterIterator);

        $this->iterator = $iterator;
        $this->themeLocation = $themeLocation;
    }


8. An error is reported at runtime. as shown in Figure 2

运行时报错
Figure 2

PS E:\wwwroot\object> php artisan theme-store:theme:install E:\wwwroot\object\resources\views\theme 12345 blade
安装主题到数据仓库

   Symfony\Component\Debug\Exception\FatalThrowableError  : Too few arguments to function Modules\ThemeStoreDB\Installer\ThemeViewRecursiveFilterIterator::__construct(), 1 passed and exactly 2 expected

  at E:\wwwroot\object\Modules\ThemeStoreDB\Installer\ThemeViewRecursiveFilterIterator.php:9
     5| class ThemeViewRecursiveFilterIterator extends \RecursiveFilterIterator
     6| {
     7|     protected $filters;
     8|
  >  9|     public function __construct(\RecursiveIterator $rit, $ignoreResults) {
    10|
    11|         $this->filters = $ignoreResults;
    12|         parent::__construct($rit);
    13|     }

  Exception trace:

  1   Modules\ThemeStoreDB\Installer\ThemeViewRecursiveFilterIterator::__construct(Object(RecursiveDirectoryIterator))
      [internal]:0

  2   RecursiveFilterIterator::getChildren()
      [internal]:0

  Please use the argument -v to see more details.


9. Edit ThemeViewRecursiveFilterIterator.php, add the method getChildren()


<?php

namespace Modules\ThemeStoreDB\Installer;

class ThemeViewRecursiveFilterIterator extends \RecursiveFilterIterator
{
    protected $filters;

    public function __construct(\RecursiveIterator $iterator, $ignoreResults) {

        $this->filters = $ignoreResults;
        parent::__construct($iterator);
    }

    public function accept() {

        $accept = true;

        if (isset($this->filters[$this->current()->getFilename()])) {
            $accept = !$this->filters[$this->current()->getFilename()];
        }

        return $accept;
    }

    public function getChildren() {
        return new self($this->getInnerIterator()->getChildren(), $this->filters);
    }

}



10. Run again, the operation is successful, but the file starting with node_modules\ is still written to the database. Not as expected. Print $this->filters


array(766) {
  [""]=>
  bool(false)
  [".browserslistrc"]=>
  bool(true)
  [".env"]=>
  bool(true)
  [".env.development"]=>
  bool(true)
  [".env.production"]=>
  bool(true)
  [".themeignore"]=>
  bool(true)
  ["assets"]=>
  bool(false)
  ["assets/css"]=>
  bool(false)
  ["assets/css/app.css"]=>
  bool(true)
  ["assets/images"]=>
  bool(false)
}


11. Print $this->current()->getPath() , $this->current()->getFileName()


E:\wwwroot\object\resources\views\theme
.browserslistrc
E:\wwwroot\object\resources\views\theme
.env
E:\wwwroot\object\resources\views\theme
.env.development
E:\wwwroot\object\resources\views\theme
.env.production
E:\wwwroot\object\resources\views\theme
.themeignore
E:\wwwroot\object\resources\views\theme
assets
E:\wwwroot\object\resources\views\theme\assets
css
E:\wwwroot\object\resources\views\theme\assets\css
app.css
E:\wwwroot\object\resources\views\theme\assets
images


12. The reason is to determine whether the file path should be filtered out is incorrect. Re-implement as follows


    /**
     * 添加忽略文件
     * @param $f
     * @param $result
     * @return void
     */
    public function addIgnoreResult($f, $result) {
        $this->ignoreResults[$this->themeLocation . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $f)] = $result;
    }



    public function accept() {
        return !$this->filters[$this->current()->getPath() . DIRECTORY_SEPARATOR . $this->current()->getFilename()];
    }


13. Run again, the operation is successful, and the file starting with node_modules has not been written to the database. in line with expectations. as shown in Figure 3

再次运行,运行成功,且 node_modules 开头的文件已未被写入至数据库中。符合预期
Figure 3

Need long-term technical maintenance or remote troubleshooting?

I am a PHP / Go backend engineer with 15+ years of experience, focused on existing system maintenance, bug fixing, performance optimization, server troubleshooting, WordPress maintenance, and small feature iterations.

If your project is facing any of the following issues, we can start with a small troubleshooting task first:

  • ✅ PHP / Laravel / Yii2 legacy systems without active maintenance
  • ✅ Go / Gin backend APIs that need troubleshooting or optimization
  • ✅ Slow, broken, or unstable WordPress websites
  • ✅ Nginx / MySQL / Redis / Linux server issues
  • ✅ CDN / Cloudflare / DNS / HTTPS configuration problems
  • ✅ Long-term remote technical support or part-time maintenance

More details: About Me & Collaboration

WeChat: 13980074657
Email: shuijingwanwq@gmail.com
Telegram: @shuijingwan
GitHub: https://github.com/shuijingwan

评论

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.