Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions en/appendices/5-4-migration-guide.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
5.4 Migration Guide
###################

The 5.4.0 release is backwards compatible with 5.0. It adds new functionality
and introduces new deprecations. Any functionality deprecated in 5.x will be
removed in 6.0.0.

Upgrade Tool
============

The :doc:`upgrade tool </appendices/migration-guides>` provides rector rules for
automating some of the migration work. Run rector before updating your
``composer.json`` dependencies::

bin/cake upgrade rector --rules cakephp54 <path/to/app/src>

Behavior Changes
================

- WIP

Deprecations
============

- WIP

New Features
============

Utility
-------

- New ``Cake\Utility\Fs\Finder`` class provides a fluent, iterator-based API for
discovering files and directories with support for pattern matching, depth
control, and custom filters. The ``Cake\Utility\Fs\Path`` class offers
cross-platform utilities for path manipulation.
1 change: 1 addition & 0 deletions en/appendices/migration-guides.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ to ensure the tool can resolve class names correctly.
./5-1-migration-guide
./5-2-migration-guide
./5-3-migration-guide
./5-4-migration-guide
./phpunit10
1 change: 1 addition & 0 deletions en/contents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Contents

core-libraries/app
core-libraries/collections
core-libraries/filesystem
core-libraries/hash
core-libraries/httpclient
core-libraries/inflector
Expand Down
292 changes: 292 additions & 0 deletions en/core-libraries/filesystem.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
Filesystem
##########

.. php:namespace:: Cake\Utility\Fs

CakePHP provides filesystem utilities for working with files and directories efficiently.
These utilities are split into two main classes:

- **Finder** - A fluent, iterator-based API for discovering files and directories
- **Path** - Static utilities for path manipulation

Finder
======

.. php:class:: Finder

The ``Finder`` class provides a lazy, iterator-based approach to discovering files and directories
with a fluent interface for building complex queries. It's memory-efficient and works consistently
across different operating systems.

Available Methods
-----------------

Location & Type
~~~~~~~~~~~~~~~

.. php:method:: in(string $directory)

Add a directory to search in. Can be called multiple times.

.. php:method:: files()

Find only files (returns iterator).

.. php:method:: directories()

Find only directories (returns iterator).

.. php:method:: all()

Find both files and directories (returns iterator).

.. php:method:: recursive(bool $recursive = true)

Enable or disable recursive directory traversal. Default is ``true``.

Filtering by Name
~~~~~~~~~~~~~~~~~

.. php:method:: name(string $pattern)

Include files/directories matching a glob pattern. Multiple calls use OR logic.

.. php:method:: notName(string $pattern)

Exclude files/directories matching a glob pattern. Multiple calls use OR logic.

Filtering by Path
~~~~~~~~~~~~~~~~~

.. php:method:: path(string $pattern)

Include files whose relative path matches a pattern (substring or regex). Multiple calls use OR logic.

.. php:method:: notPath(string $pattern)

Exclude files whose relative path matches a pattern (substring or regex). Multiple calls use OR logic.

.. php:method:: pattern(string $globPattern)

Include files matching a glob pattern against the full relative path. Supports ``**`` for recursive matching.

.. php:method:: exclude(string $directory)

Exclude specific directories from traversal. More efficient than filtering.

Depth Control
~~~~~~~~~~~~~

.. php:method:: depth(int $depth, DepthOperator $operator = DepthOperator::EQUAL)

Filter by directory depth using operators like EQUAL, LESS_THAN, GREATER_THAN, etc.

Custom Filtering
~~~~~~~~~~~~~~~~

.. php:method:: filter(callable $callback)

Apply custom filter callback. Receives ``SplFileInfo`` and relative path. Multiple calls use AND logic.

.. php:method:: ignoreHiddenFiles()

Exclude hidden files (files starting with ``.``).

Basic Usage
-----------

Finding Files and Directories
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Find all PHP files in a directory::

use Cake\Utility\Fs\Finder;

$finder = (new Finder())
->in('src')
->name('*.php')
->files();

foreach ($files as $file) {
echo $file->getPathname();
}

Find directories while excluding certain ones::

$directories = (new Finder())
->in('src')
->exclude('vendor')
->exclude('tmp')
->directories();

By default, the Finder searches recursively. Use ``recursive(false)`` for top-level only::

$finder = (new Finder())
->in('src')
->recursive(false)
->files();

Filtering Examples
------------------

By Filename Pattern
~~~~~~~~~~~~~~~~~~~

Include and exclude specific filename patterns::

$finder = (new Finder())
->in('src')
->name('*.php') // Include all PHP files
->notName('*Test.php') // Exclude test files
->notName('*Fixture.php') // Exclude fixtures
->files();

By Path Pattern
~~~~~~~~~~~~~~~

Filter by path containing specific strings or regex patterns::

$finder = (new Finder())
->in('src')
->path('Controller') // Include paths containing "Controller"
->notPath('Test') // Exclude paths containing "Test"
->path('/Controller\.php$/') // Or use regex patterns
->files();

By Depth
~~~~~~~~

Control traversal depth using type-safe operators::

use Cake\Utility\Fs\Enum\DepthOperator;

// Maximum depth of 3
$finder = (new Finder())
->in('src')
->depth(3, DepthOperator::LESS_THAN)
->files();

// Depth range (1, 2, or 3)
$finder = (new Finder())
->in('src')
->depth(0, DepthOperator::GREATER_THAN)
->depth(4, DepthOperator::LESS_THAN)
->files();

Available depth operators: ``EQUAL``, ``NOT_EQUAL``, ``LESS_THAN``, ``GREATER_THAN``,
``LESS_THAN_OR_EQUAL``, ``GREATER_THAN_OR_EQUAL``.

Using Glob Patterns
~~~~~~~~~~~~~~~~~~~

Use glob patterns with ``**`` for recursive matching::

$finder = (new Finder())
->in('.')
->pattern('src/**/*Controller.php')
->pattern('tests/**/*Test.php')
->files();

Glob syntax: ``*`` matches any characters except ``/``, ``**`` matches including ``/``,
``?`` matches single character, ``[abc]`` matches any character in set.

Custom Filters
~~~~~~~~~~~~~~

For complex filtering, use custom callbacks::

use SplFileInfo;

$finder = (new Finder())
->in('src')
->filter(fn(SplFileInfo $file) => $file->getSize() > 1024)
->filter(fn(SplFileInfo $file) => $file->getMTime() > strtotime('-1 week'))
->files();

The callback receives ``SplFileInfo`` and the relative path::

$finder = (new Finder())
->in('.')
->filter(function (SplFileInfo $file, string $relativePath) {
return str_starts_with($relativePath, 'src/Controller')
|| str_starts_with($relativePath, 'src/Model');
})
->files();

Complete Example
----------------

Combining multiple filters::

use Cake\Utility\Fs\Finder;
use Cake\Utility\Fs\Enum\DepthOperator;

$finder = (new Finder())
->in('src')
->in('plugins')
->name('*.php')
->notName('*Test.php')
->exclude('vendor')
->exclude('tmp')
->path('Controller')
->depth(5, DepthOperator::LESS_THAN)
->ignoreHiddenFiles()
->files();

foreach ($finder as $file) {
echo $file->getRealPath() . PHP_EOL;
}

Path
====

.. php:class:: Path

The ``Path`` class provides static utilities for path manipulation.

Available Methods
-----------------

.. php:staticmethod:: normalize(string $path)

Convert paths to use forward slashes.

.. php:staticmethod:: makeRelative(string $path, string $base)

Convert an absolute path to a relative path based on a base directory.

.. php:staticmethod:: join(string ...$segments)

Join multiple path segments into a single path.

.. php:staticmethod:: matches(string $pattern, string $path)

Test if a path matches a glob pattern. Supports ``*``, ``**``, ``?``, and ``[abc]`` syntax.

Examples
--------

::

use Cake\Utility\Fs\Path;

// Normalize path separators
Path::normalize('path\\to\\file.php');
// Returns: 'path/to/file.php'

// Make relative paths
Path::makeRelative('/var/www/app/src/Controller/UsersController.php', '/var/www/app');
// Returns: 'src/Controller/UsersController.php'

// Join path segments
Path::join('src', 'Controller', 'UsersController.php');
// Returns: 'src/Controller/UsersController.php'

// Match glob patterns
Path::matches('*.php', 'test.php'); // true
Path::matches('src/**/*.php', 'src/Controller/UsersController.php'); // true
Path::matches('src/**/Test/*.php', 'src/Controller/UsersController.php'); // false

.. meta::
:title lang=en: Filesystem
:keywords lang=en: finder,filesystem,files,directories,glob,path,iterator,fluent interface,cross-platform