PHPackages                             pfaciana/includefile - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. pfaciana/includefile

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

pfaciana/includefile
====================

Include-pattern matcher built on automattic/ignorefile

0.3.0(2w ago)047↓36.2%GPL-2.0-onlyPHPPHP ^8.1CI passing

Since May 17Pushed 2w agoCompare

[ Source](https://github.com/pfaciana/includefile)[ Packagist](https://packagist.org/packages/pfaciana/includefile)[ Docs](https://renderdev.com/)[ RSS](/packages/pfaciana-includefile/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (5)Dependencies (2)Versions (6)Used By (0)

includefile
===========

[](#includefile)

`includefile` is an include-pattern matcher designed for fast filesystem discovery.

It wraps [`automattic/ignorefile`](https://github.com/Automattic/ignorefile), but exposes include-first behavior: describe the files you want, exclude the directories or files you do not want, and stream the matching entries into whatever processing step comes next.

Installation
------------

[](#installation)

```
composer require pfaciana/includefile
```

Pattern Model
-------------

[](#pattern-model)

Patterns are include-first.

```
src         include the src directory and descendants
**/*.php    include PHP files anywhere
!vendor     exclude the vendor directory and descendants

```

The pattern syntax comes from Git-style ignore files, through `automattic/ignorefile`. Use Git ignore-pattern behavior as the baseline model; this package does NOT define a new glob language.

Internally, `includefile` converts include patterns into ignore-style rules for `automattic/ignorefile`. That matters because `!` means "exclude from the include set" in this package, even though `!` means "unignore" in a `.gitignore` file.

`automattic/ignorefile` compiles patterns to regex. It does not check the filesystem to find out whether an ambiguous path is a file or a directory. A pattern like `.examples` could refer to either one, so `includefile` has to classify ambiguous patterns before it can build traversal filters.

### Ambiguous Files vs Directories

[](#ambiguous-files-vs-directories)

`includefile` classifies patterns as file patterns or directory patterns. That classification is a best guess based on the pattern text, not a filesystem check. It is used when building traversal filters.

Default rules:

- A final path segment with no dots is treated as a directory: `src`, `vendor`, `bin/console`, `v1.2/config`.
- A final path segment with a dot is treated as a file: `index.php`, `src/config.json`.
- EXCEPT: Single-dot hidden names are treated as directories: `.git`, `.agents`, `.claude`, `.env`, `.gitignore`.

So in short, `no dot = directory`, `dot = file`, unless hidden `hidden dot = directory`.

Force rules:

If you dont want to leave anything to change, you force how a pattern is treated.

- A trailing `/`, `/*`, or `/**` makes the pattern a directory pattern.
- `@file:` forces a pattern to be treated as a file: `@file:README`, `@file:bin/console`, `@file:.env`, `@file:.gitignore`.
    - Negation works with `@file:` by putting `!` first: `!@file:README`, `!@file:.env`, `!@file:.gitignore` you're saying `DO NOT INCLUDE` (or `EXCLUDE`) this file.

Hidden names are biased toward directories because directory pruning is usually more important for names like `.git`, `.agents`, and `.claude`. Files like `.gitattributes`, `.gitignore`, and `.env` do exist; use `@file:` when the hidden pattern is meant to be a file.

So in short, `end in slash = directory`, `starts with @file: (or !@file:) = file`.

### Directory Pruning

[](#directory-pruning)

Some excluded directory patterns are terminal during traversal.

```
!vendor
!.git
!node_modules

```

These exclude the directory and descendants, so discovery can skip descending into them.

Open-ended exclusions are different:

```
!vendor/*
!vendor/**

```

Those exclude contents but are not terminal, because a later include pattern may still make a descendant reachable.

```
src
!src/vendor/*
src/vendor/acme

```

Use terminal exclusions when nothing under that directory should be discovered. Use open-ended exclusions when later include patterns may re-include descendants.

This follows the same reachability model as Git ignore files, with the include/exclude meaning inverted. If traversal excludes a directory itself, later patterns for descendants under that directory cannot be reached during filesystem discovery.

File Discovery
--------------

[](#file-discovery)

A common use is to stream matching files from a base directory.

```
use Render\IncludeFile;

$include = new IncludeFile( [
	'**/*.php',
	'!.git',
	'!node_modules',
	'!tests',
	'!vendor',
] );

$baseDir = IncludeFile::add_trailing_slash( IncludeFile::normalize( __DIR__ ) );

$files = IncludeFile::get_files( $baseDir, [
	'filter' => $include->getFilter( $baseDir ),
] );

foreach ( $files as $file ) {
	// Process each matching SplFileInfo entry.
}
```

`get_files()` returns a generator. The default callback filter uses the include patterns for files and prunes terminal excluded directories before descending into them.

### `get_files()`

[](#get_files)

`IncludeFile::get_files()` is the common helper for filesystem discovery. It creates the recursive iterators, applies an optional traversal filter, and yields matching entries.

```
IncludeFile::get_files( string|array $directories, array|callable|string|null $config = NULL ): \Generator
```

The first argument is a directory path or a list of directory paths.

The second argument may be:

- `NULL` to walk without a filter.
- A callable filter, passed directly to `RecursiveCallbackFilterIterator`.
- A string extension or dotted filename suffix, normalized to `filterByExt`.
- A list of string extensions or dotted filename suffixes, normalized to `filterByExt`.
- A config array.

Config keys:

- `filter`: callable filter or `FALSE`.
- `filterByExt`: string or list of extensions/dotted filename suffixes to filter yielded files.
- `maxDepth`: maximum recursive depth, default `50`.
- `flags`: `RecursiveDirectoryIterator` flags.
- `mode`: `RecursiveIteratorIterator` mode, default `RecursiveIteratorIterator::LEAVES_ONLY`.

Extension filters are case-insensitive. Values like `'php'`, `'.php'`, and `'*.php'` are equivalent. Dotted suffixes like `'inc.php'` match the full filename suffix. An empty string matches extensionless files, and an empty list means no extension filter. Unsupported `filterByExt` values are treated as no extension filter.

Use it with `getFilter()` for normal include-pattern discovery. Use `filterByExt` beside `filter` when you want include-pattern filtering and extension filtering together. The built-in `filterByExt` check is for the default leaf/fileinfo traversal; use a callable filter when custom iterator modes or current modes need extension filtering.

```
$phpFiles = IncludeFile::get_files( $baseDir, 'php' );
$assetFiles = IncludeFile::get_files( $baseDir, [ 'php', 'json', 'md' ] );

$includedPhpFiles = IncludeFile::get_files( $baseDir, [
	'filter'      => $include->getFilter( $baseDir ),
	'filterByExt' => 'php',
] );
```

Custom Discovery Filters
------------------------

[](#custom-discovery-filters)

Use `makeFilter()` to extend the default callback filter without replacing its include-pattern behavior. Pass `'allowLinks' => TRUE` to `getFilter()` or `makeFilter()` to let the traversal filter treat linked directories as children.

The optional callbacks receive:

```
'dir'  => function ( $iterator, $fileInfo, string $absPath, string $relPath, string $baseDir, IncludeFile|false $includeDirs, IncludeFile $include ): ?bool
'file' => function ( $fileInfo, $iterator, string $absPath, string $relPath, string $baseDir, IncludeFile $include, IncludeFile|false $includeDirs ): ?bool
```

Return `TRUE` or `FALSE` to short-circuit the default filter. Return `NULL` to continue to the default behavior.

Callbacks may omit trailing parameters, but declared parameters must keep the documented order.

```
$filter = $include->makeFilter( $baseDir, [
	'file' => function ( $fileInfo, $iterator, string $absPath, string $relPath ): ?bool {
		if ( str_contains( $relPath, '/generated/' ) ) {
			return FALSE;
		}

		return NULL;
	},
] );
```

For extension filtering, use `get_files()` with `filterByExt`. For default traversal behavior, `getFilter()` is shorthand for `makeFilter( $baseDir )`.

`getDefaultCallbackFilter()` is still available as a deprecated compatibility alias.

`filterByExt` is useful when the caller only wants specific file types. It runs after the traversal filter and before yielding files, so `filter` can prune directories while `filterByExt` keeps extension checks out of custom callback code.

See `examples/file-discovery-basic.php` for a direct file discovery example.

See `examples/file-discovery-advanced.php` for the full wrapper-style example. It normalizes a base directory, builds a reusable discovery function, adapts the native `RecursiveCallbackFilterIterator` callback, and passes extra context into the caller's custom filter.

See `examples/get-files.php` for using `get_files()` without include patterns.

Direct Pattern Matching
-----------------------

[](#direct-pattern-matching)

If you dont need to discover files, meaning you already know the exact files you want to test, then you can use the `includes()` and `filter()` methods.

Use `includes()` when you already have a path and only need to test it.

```
$include = new IncludeFile( [
	'@file:README',
	'src',
	'!src/private',
] );

if ( $include->includes( 'src/IncludeFile.php' ) ) {
	// Included.
}
```

Use `filter()` when you already have an array of paths.

```
$filesToProcess = $include->filter( $allFiles );
```

Use `test()` when you need the include state and the matching pattern.

```
$result = $include->test( 'src/private/Secret.php' );

// [
//     'included' => false,
//     'notIncluded' => true,
//     'pattern' => '!src/private',
// ]
```

Gotchas
-------

[](#gotchas)

When testing a raw directory path string with `includes()`, include the trailing `/`. Without it, `automattic/ignorefile` treats the path like a file path.

```
$include->includes( 'src/' ); // directory path string
$include->includes( 'src' );  // file-like path string
```

This is separate from pattern classification. As a pattern, `src` is treated as a directory pattern and includes `src` and descendants.

Strict mode is enabled by default. Invalid patterns throw `Automattic\IgnoreFile\InvalidPatternException`.

```
$include->setStrictMode( false );
```

Pattern parsing comes from `automattic/ignorefile`; known incompatibilities with Git are inherited from that package.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance97

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

5

Last Release

16d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7454630?v=4)[Phil Faciana](/maintainers/pfaciana)[@pfaciana](https://github.com/pfaciana)

---

Top Contributors

[![pfaciana](https://avatars.githubusercontent.com/u/7454630?v=4)](https://github.com/pfaciana "pfaciana (1 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/pfaciana-includefile/health.svg)

```
[![Health](https://phpackages.com/badges/pfaciana-includefile/health.svg)](https://phpackages.com/packages/pfaciana-includefile)
```

###  Alternatives

[gongo/merciful-polluter

Emulate `register\_globals` and `magic\_quotes\_gpc` in PHP 5.4 or higher

1715.8k](/packages/gongo-merciful-polluter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
