1 Painfree Handling of File Paths
2 ===============================
4 Dealing with file paths usually involves some difficulties:
6 * **System Heterogeneity**: File paths look different on different platforms.
7 UNIX file paths start with a slash ("/"), while Windows file paths start with
8 a system drive ("C:"). UNIX uses forward slashes, while Windows uses
9 backslashes by default ("\").
11 * **Absolute/Relative Paths**: Web applications frequently need to deal with
12 absolute and relative paths. Converting one to the other properly is tricky
15 This package provides few, but robust utility methods to simplify your life
16 when dealing with file paths.
21 *Canonicalization* is the transformation of a path into a normalized (the
22 "canonical") format. You can canonicalize a path with `Path::canonicalize()`:
25 echo Path::canonicalize('/var/www/vhost/webmozart/../config.ini');
26 // => /var/www/vhost/config.ini
29 The following modifications happen during canonicalization:
31 * "." segments are removed;
32 * ".." segments are resolved;
33 * backslashes ("\") are converted into forward slashes ("/");
34 * root paths ("/" and "C:/") always terminate with a slash;
35 * non-root paths never terminate with a slash;
36 * schemes (such as "phar://") are kept;
37 * replace "~" with the user's home directory.
39 You can pass absolute paths and relative paths to `canonicalize()`. When a
40 relative path is passed, ".." segments at the beginning of the path are kept:
43 echo Path::canonicalize('../uploads/../config/config.yml');
44 // => ../config/config.yml
47 Malformed paths are returned unchanged:
50 echo Path::canonicalize('C:Programs/PHP/php.ini');
51 // => C:Programs/PHP/php.ini
54 Converting Absolute/Relative Paths
55 ----------------------------------
57 Absolute/relative paths can be converted with the methods `Path::makeAbsolute()`
58 and `Path::makeRelative()`.
60 `makeAbsolute()` expects a relative path and a base path to base that relative
64 echo Path::makeAbsolute('config/config.yml', '/var/www/project');
65 // => /var/www/project/config/config.yml
68 If an absolute path is passed in the first argument, the absolute path is
72 echo Path::makeAbsolute('/usr/share/lib/config.ini', '/var/www/project');
73 // => /usr/share/lib/config.ini
76 The method resolves ".." segments, if there are any:
79 echo Path::makeAbsolute('../config/config.yml', '/var/www/project/uploads');
80 // => /var/www/project/config/config.yml
83 This method is very useful if you want to be able to accept relative paths (for
84 example, relative to the root directory of your project) and absolute paths at
87 `makeRelative()` is the inverse operation to `makeAbsolute()`:
90 echo Path::makeRelative('/var/www/project/config/config.yml', '/var/www/project');
91 // => config/config.yml
94 If the path is not within the base path, the method will prepend ".." segments
98 echo Path::makeRelative('/var/www/project/config/config.yml', '/var/www/project/uploads');
99 // => ../config/config.yml
102 Use `isAbsolute()` and `isRelative()` to check whether a path is absolute or
106 Path::isAbsolute('C:\Programs\PHP\php.ini')
110 All four methods internally canonicalize the passed path.
112 Finding Longest Common Base Paths
113 ---------------------------------
115 When you store absolute file paths on the file system, this leads to a lot of
116 duplicated information:
120 '/var/www/vhosts/project/httpdocs/config/config.yml',
121 '/var/www/vhosts/project/httpdocs/config/routing.yml',
122 '/var/www/vhosts/project/httpdocs/config/services.yml',
123 '/var/www/vhosts/project/httpdocs/images/banana.gif',
124 '/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
128 Especially when storing many paths, the amount of duplicated information is
129 noticeable. You can use `Path::getLongestCommonBasePath()` to check a list of
130 paths for a common base path:
134 '/var/www/vhosts/project/httpdocs/config/config.yml',
135 '/var/www/vhosts/project/httpdocs/config/routing.yml',
136 '/var/www/vhosts/project/httpdocs/config/services.yml',
137 '/var/www/vhosts/project/httpdocs/images/banana.gif',
138 '/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
141 Path::getLongestCommonBasePath($paths);
142 // => /var/www/vhosts/project/httpdocs
145 Use this path together with `Path::makeRelative()` to shorten the stored paths:
148 $bp = '/var/www/vhosts/project/httpdocs';
151 $bp.'/config/config.yml',
152 $bp.'/config/routing.yml',
153 $bp.'/config/services.yml',
154 $bp.'/images/banana.gif',
155 $bp.'/uploads/images/nicer-banana.gif',
159 `getLongestCommonBasePath()` always returns canonical paths.
161 Use `Path::isBasePath()` to test whether a path is a base path of another path:
164 Path::isBasePath("/var/www", "/var/www/project");
167 Path::isBasePath("/var/www", "/var/www/project/..");
170 Path::isBasePath("/var/www", "/var/www/project/../..");
174 Finding Directories/Root Directories
175 ------------------------------------
177 PHP offers the function `dirname()` to obtain the directory path of a file path.
178 This method has a few quirks:
180 * `dirname()` does not accept backslashes on UNIX
181 * `dirname("C:/Programs")` returns "C:", not "C:/"
182 * `dirname("C:/")` returns ".", not "C:/"
183 * `dirname("C:")` returns ".", not "C:/"
184 * `dirname("Programs")` returns ".", not ""
185 * `dirname()` does not canonicalize the result
187 `Path::getDirectory()` fixes these shortcomings:
190 echo Path::getDirectory("C:\Programs");
194 Additionally, you can use `Path::getRoot()` to obtain the root of a path:
197 echo Path::getRoot("/etc/apache2/sites-available");
200 echo Path::getRoot("C:\Programs\Apache\Config");