Skip to content

Commit 289ce98

Browse files
committed
Merge branch '5.4' into 6.0
* 5.4: Minor tweaks [Filesystem] Add documentation for the Path class
2 parents 3131a42 + 304de64 commit 289ce98

File tree

1 file changed

+196
-4
lines changed

1 file changed

+196
-4
lines changed

components/filesystem.rst

Lines changed: 196 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 platform-independent utilities for
8+
filesystem operations and for file/directory paths manipulation.
89

910
Installation
1011
------------
@@ -18,20 +19,26 @@ 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 main classes called :class:`Symfony\\Component\\Filesystem\\Filesystem`
23+
and :class:`Symfony\\Component\\Filesystem\\Path`::
2324

2425
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
2526
use Symfony\Component\Filesystem\Filesystem;
27+
use Symfony\Component\Filesystem\Path;
2628

2729
$filesystem = new Filesystem();
2830

2931
try {
30-
$filesystem->mkdir(sys_get_temp_dir().'/'.random_int(0, 1000));
32+
$filesystem->mkdir(
33+
Path::normalize(sys_get_temp_dir().'/'.random_int(0, 1000)),
34+
);
3135
} catch (IOExceptionInterface $exception) {
3236
echo "An error occurred while creating your directory at ".$exception->getPath();
3337
}
3438

39+
Filesystem Utilities
40+
--------------------
41+
3542
``mkdir``
3643
~~~~~~~~~
3744

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

234+
.. note::
235+
236+
If you wish to canonicalize the path without checking its existence, you can
237+
use :method:`Symfony\\Component\\Filesystem\\Path::canonicalize` method instead.
238+
227239
``makePathRelative``
228240
~~~~~~~~~~~~~~~~~~~~
229241

@@ -301,6 +313,186 @@ contents at the end of some file::
301313
If either the file or its containing directory doesn't exist, this method
302314
creates them before appending the contents.
303315

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

0 commit comments

Comments
 (0)