Skip to content

Commit 44fd61e

Browse files
committed
minor #15759 [Filesystem] Add documentation for the Path class (theofidry)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [Filesystem] Add documentation for the Path class <!-- If your pull request fixes a BUG, use the oldest maintained branch that contains the bug (see https://symfony.com/releases for the list of maintained branches). If your pull request documents a NEW FEATURE, use the same Symfony branch where the feature was introduced (and `5.x` for features of unreleased versions). --> Closes #15621 Commits ------- 165244e [Filesystem] Add documentation for the Path class
2 parents 92139e5 + 165244e commit 44fd61e

File tree

1 file changed

+206
-4
lines changed

1 file changed

+206
-4
lines changed

components/filesystem.rst

Lines changed: 206 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
The Filesystem Component
55
========================
66

7-
The Filesystem component provides basic utilities for the filesystem.
7+
The Filesystem component provides basic utilities for the filesystem and
8+
paths manipulation.
89

910
Installation
1011
------------
@@ -18,20 +19,30 @@ Installation
1819
Usage
1920
-----
2021

21-
The :class:`Symfony\\Component\\Filesystem\\Filesystem` class is the unique
22-
endpoint for filesystem operations::
22+
The component contains two classes:
23+
24+
- The :class:`Symfony\\Component\\Filesystem\\Filesystem` which provides utilities
25+
for filesystem write operations.
26+
- The :class:`Symfony\\Component\\Filesystem\\Path` which provides utilities
27+
for paths manipulation.::
2328

2429
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
2530
use Symfony\Component\Filesystem\Filesystem;
31+
use Symfony\Component\Filesystem\Path;
2632

2733
$filesystem = new Filesystem();
2834

2935
try {
30-
$filesystem->mkdir(sys_get_temp_dir().'/'.random_int(0, 1000));
36+
$filesystem->mkdir(
37+
Path::normalize(sys_get_temp_dir().'/'.random_int(0, 1000)),
38+
);
3139
} catch (IOExceptionInterface $exception) {
3240
echo "An error occurred while creating your directory at ".$exception->getPath();
3341
}
3442

43+
Filesystem
44+
----------
45+
3546
``mkdir``
3647
~~~~~~~~~
3748

@@ -224,6 +235,11 @@ Its behavior is the following::
224235
* if ``$path`` does not exist, it returns null.
225236
* if ``$path`` exists, it returns its absolute fully resolved final version.
226237

238+
.. note::
239+
240+
If you wish to canonicalize the path without checking its existence, you can
241+
use :method:`Symfony\\Component\\Filesystem\\Path::canonicalize` method instead.
242+
227243
``makePathRelative``
228244
~~~~~~~~~~~~~~~~~~~~
229245

@@ -309,6 +325,192 @@ creates them before appending the contents.
309325

310326
The third argument of ``appendToFile()`` was introduced in Symfony 5.4.
311327

328+
Path
329+
----
330+
331+
.. versionadded:: 5.4
332+
333+
The :class:`Symfony\\Component\\Filesystem\\Path` class was introduced in Symfony 5.4.
334+
335+
Dealing with file paths usually involves some difficulties:
336+
337+
- System Heterogeneity: file paths look different on different platforms. UNIX
338+
file paths start with a slash ("/"), while Windows file paths start with a
339+
system drive ("C:"). UNIX uses forward slashes, while Windows uses backslashes
340+
by default ("").
341+
- Absolute/relative paths: web applications frequently need to deal with absolute
342+
and relative paths. Converting one to the other properly is tricky and
343+
repetitive.
344+
345+
:class:`Symfony\\Component\\Filesystem\\Path` provides utility methods to tackle
346+
those issues.
347+
348+
Canonicalization
349+
~~~~~~~~~~~~~~~~
350+
351+
Returns the shortest path name equivalent to the given path. It applies the
352+
following rules iteratively until no further processing can be done:
353+
354+
- "." segments are removed;
355+
- ".." segments are resolved;
356+
- backslashes ("\") are converted into forward slashes ("/");
357+
- root paths ("/" and "C:/") always terminate with a slash;
358+
- non-root paths never terminate with a slash;
359+
- schemes (such as "phar://") are kept;
360+
- replace "~" with the user's home directory.
361+
362+
You can canonicalize a path with :method:`Symfony\\Component\\Filesystem\\Path::canonicalize`::
363+
364+
echo Path::canonicalize('/var/www/vhost/webmozart/../config.ini');
365+
// => /var/www/vhost/config.ini
366+
367+
You can pass absolute paths and relative paths to the
368+
:method:`Symfony\\Component\\Filesystem\\Path::canonicalize` method. When a
369+
relative path is passed, ".." segments at the beginning of the path are kept::
370+
371+
echo Path::canonicalize('../uploads/../config/config.yaml');
372+
// => ../config/config.yaml
373+
374+
Malformed paths are returned unchanged::
375+
376+
echo Path::canonicalize('C:Programs/PHP/php.ini');
377+
// => C:Programs/PHP/php.ini
378+
379+
Converting Absolute/Relative Paths
380+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
381+
382+
Absolute/relative paths can be converted with the methods
383+
:method:`Symfony\\Component\\Filesystem\\Path::makeAbsolute`
384+
and :method:`Symfony\\Component\\Filesystem\\Path::makeRelative`.
385+
386+
:method:`Symfony\\Component\\Filesystem\\Path::makeAbsolute` method expects a
387+
relative path and a base path to base that relative path upon::
388+
389+
echo Path::makeAbsolute('config/config.yaml', '/var/www/project');
390+
// => /var/www/project/config/config.yaml
391+
392+
If an absolute path is passed in the first argument, the absolute path is
393+
returned unchanged::
394+
395+
echo Path::makeAbsolute('/usr/share/lib/config.ini', '/var/www/project');
396+
// => /usr/share/lib/config.ini
397+
398+
The method resolves ".." segments, if there are any::
399+
400+
echo Path::makeAbsolute('../config/config.yaml', '/var/www/project/uploads');
401+
// => /var/www/project/config/config.yaml
402+
403+
This method is very useful if you want to be able to accept relative paths (for
404+
example, relative to the root directory of your project) and absolute paths at
405+
the same time.
406+
407+
:method:`Symfony\\Component\\Filesystem\\Path::makeRelative` is the inverse
408+
operation to :method:`Symfony\\Component\\Filesystem\\Path::makeAbsolute`::
409+
410+
echo Path::makeRelative('/var/www/project/config/config.yaml', '/var/www/project');
411+
// => config/config.yaml
412+
413+
If the path is not within the base path, the method will prepend ".." segments
414+
as necessary::
415+
416+
echo Path::makeRelative('/var/www/project/config/config.yaml', '/var/www/project/uploads');
417+
// => ../config/config.yaml
418+
419+
Use :method:`Symfony\\Component\\Filesystem\\Path::makeAbsolute` and
420+
:method:`Symfony\\Component\\Filesystem\\Path::makeRelative` to check whether a
421+
path is absolute or relative::
422+
423+
Path::isAbsolute('C:\Programs\PHP\php.ini')
424+
// => true
425+
426+
All four methods internally canonicalize the passed path.
427+
428+
Finding Longest Common Base Paths
429+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
430+
431+
When you store absolute file paths on the file system, this leads to a lot of
432+
duplicated information::
433+
434+
return [
435+
'/var/www/vhosts/project/httpdocs/config/config.yaml',
436+
'/var/www/vhosts/project/httpdocs/config/routing.yaml',
437+
'/var/www/vhosts/project/httpdocs/config/services.yaml',
438+
'/var/www/vhosts/project/httpdocs/images/banana.gif',
439+
'/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
440+
];
441+
442+
Especially when storing many paths, the amount of duplicated information is
443+
noticeable. You can use :method:`Symfony\\Component\\Filesystem\\Path::getLongestCommonBasePath`
444+
to check a list of paths for a common base path::
445+
446+
$paths = [
447+
'/var/www/vhosts/project/httpdocs/config/config.yaml',
448+
'/var/www/vhosts/project/httpdocs/config/routing.yaml',
449+
'/var/www/vhosts/project/httpdocs/config/services.yaml',
450+
'/var/www/vhosts/project/httpdocs/images/banana.gif',
451+
'/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
452+
];
453+
454+
Path::getLongestCommonBasePath($paths);
455+
// => /var/www/vhosts/project/httpdocs
456+
457+
Use this path together with :method:`Symfony\\Component\\Filesystem\\Path::makeRelative`
458+
to shorten the stored paths::
459+
460+
$bp = '/var/www/vhosts/project/httpdocs';
461+
462+
return [
463+
$bp.'/config/config.yaml',
464+
$bp.'/config/routing.yaml',
465+
$bp.'/config/services.yaml',
466+
$bp.'/images/banana.gif',
467+
$bp.'/uploads/images/nicer-banana.gif',
468+
];
469+
470+
:method:`Symfony\\Component\\Filesystem\\Path::getLongestCommonBasePath` always
471+
returns canonical paths.
472+
473+
Use :method:`Symfony\\Component\\Filesystem\\Path::isBasePath` to test whether a
474+
path is a base path of another path::
475+
476+
Path::isBasePath("/var/www", "/var/www/project");
477+
// => true
478+
479+
Path::isBasePath("/var/www", "/var/www/project/..");
480+
// => true
481+
482+
Path::isBasePath("/var/www", "/var/www/project/../..");
483+
// => false
484+
485+
Finding Directories/Root Directories
486+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
487+
488+
PHP offers the function :phpfunction:`dirname` to obtain the directory path of a
489+
file path. This method has a few quirks::
490+
491+
- `dirname()` does not accept backslashes on UNIX
492+
- `dirname("C:/Programs")` returns "C:", not "C:/"
493+
- `dirname("C:/")` returns ".", not "C:/"
494+
- `dirname("C:")` returns ".", not "C:/"
495+
- `dirname("Programs")` returns ".", not ""
496+
- `dirname()` does not canonicalize the result
497+
498+
:method:`Symfony\\Component\\Filesystem\\Path::getDirectory` fixes these
499+
shortcomings::
500+
501+
echo Path::getDirectory("C:\Programs");
502+
// => C:/
503+
504+
Additionally, you can use :method:`Symfony\\Component\\Filesystem\\Path::getRoot`
505+
to obtain the root of a path::
506+
507+
echo Path::getRoot("/etc/apache2/sites-available");
508+
// => /
509+
510+
echo Path::getRoot("C:\Programs\Apache\Config");
511+
// => C:/
512+
>>>>>>> a992f6342 ([Filesystem] Add documentation for the Path class)
513+
312514
Error Handling
313515
--------------
314516

0 commit comments

Comments
 (0)