annotate vendor/webmozart/path-util/docs/usage.md @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 Painfree Handling of File Paths
Chris@0 2 ===============================
Chris@0 3
Chris@0 4 Dealing with file paths usually involves some difficulties:
Chris@0 5
Chris@0 6 * **System Heterogeneity**: File paths look different on different platforms.
Chris@0 7 UNIX file paths start with a slash ("/"), while Windows file paths start with
Chris@0 8 a system drive ("C:"). UNIX uses forward slashes, while Windows uses
Chris@0 9 backslashes by default ("\").
Chris@0 10
Chris@0 11 * **Absolute/Relative Paths**: Web applications frequently need to deal with
Chris@0 12 absolute and relative paths. Converting one to the other properly is tricky
Chris@0 13 and repetitive.
Chris@0 14
Chris@0 15 This package provides few, but robust utility methods to simplify your life
Chris@0 16 when dealing with file paths.
Chris@0 17
Chris@0 18 Canonicalization
Chris@0 19 ----------------
Chris@0 20
Chris@0 21 *Canonicalization* is the transformation of a path into a normalized (the
Chris@0 22 "canonical") format. You can canonicalize a path with `Path::canonicalize()`:
Chris@0 23
Chris@0 24 ```php
Chris@0 25 echo Path::canonicalize('/var/www/vhost/webmozart/../config.ini');
Chris@0 26 // => /var/www/vhost/config.ini
Chris@0 27 ```
Chris@0 28
Chris@0 29 The following modifications happen during canonicalization:
Chris@0 30
Chris@0 31 * "." segments are removed;
Chris@0 32 * ".." segments are resolved;
Chris@0 33 * backslashes ("\") are converted into forward slashes ("/");
Chris@0 34 * root paths ("/" and "C:/") always terminate with a slash;
Chris@0 35 * non-root paths never terminate with a slash;
Chris@0 36 * schemes (such as "phar://") are kept;
Chris@0 37 * replace "~" with the user's home directory.
Chris@0 38
Chris@0 39 You can pass absolute paths and relative paths to `canonicalize()`. When a
Chris@0 40 relative path is passed, ".." segments at the beginning of the path are kept:
Chris@0 41
Chris@0 42 ```php
Chris@0 43 echo Path::canonicalize('../uploads/../config/config.yml');
Chris@0 44 // => ../config/config.yml
Chris@0 45 ```
Chris@0 46
Chris@0 47 Malformed paths are returned unchanged:
Chris@0 48
Chris@0 49 ```php
Chris@0 50 echo Path::canonicalize('C:Programs/PHP/php.ini');
Chris@0 51 // => C:Programs/PHP/php.ini
Chris@0 52 ```
Chris@0 53
Chris@0 54 Converting Absolute/Relative Paths
Chris@0 55 ----------------------------------
Chris@0 56
Chris@0 57 Absolute/relative paths can be converted with the methods `Path::makeAbsolute()`
Chris@0 58 and `Path::makeRelative()`.
Chris@0 59
Chris@0 60 `makeAbsolute()` expects a relative path and a base path to base that relative
Chris@0 61 path upon:
Chris@0 62
Chris@0 63 ```php
Chris@0 64 echo Path::makeAbsolute('config/config.yml', '/var/www/project');
Chris@0 65 // => /var/www/project/config/config.yml
Chris@0 66 ```
Chris@0 67
Chris@0 68 If an absolute path is passed in the first argument, the absolute path is
Chris@0 69 returned unchanged:
Chris@0 70
Chris@0 71 ```php
Chris@0 72 echo Path::makeAbsolute('/usr/share/lib/config.ini', '/var/www/project');
Chris@0 73 // => /usr/share/lib/config.ini
Chris@0 74 ```
Chris@0 75
Chris@0 76 The method resolves ".." segments, if there are any:
Chris@0 77
Chris@0 78 ```php
Chris@0 79 echo Path::makeAbsolute('../config/config.yml', '/var/www/project/uploads');
Chris@0 80 // => /var/www/project/config/config.yml
Chris@0 81 ```
Chris@0 82
Chris@0 83 This method is very useful if you want to be able to accept relative paths (for
Chris@0 84 example, relative to the root directory of your project) and absolute paths at
Chris@0 85 the same time.
Chris@0 86
Chris@0 87 `makeRelative()` is the inverse operation to `makeAbsolute()`:
Chris@0 88
Chris@0 89 ```php
Chris@0 90 echo Path::makeRelative('/var/www/project/config/config.yml', '/var/www/project');
Chris@0 91 // => config/config.yml
Chris@0 92 ```
Chris@0 93
Chris@0 94 If the path is not within the base path, the method will prepend ".." segments
Chris@0 95 as necessary:
Chris@0 96
Chris@0 97 ```php
Chris@0 98 echo Path::makeRelative('/var/www/project/config/config.yml', '/var/www/project/uploads');
Chris@0 99 // => ../config/config.yml
Chris@0 100 ```
Chris@0 101
Chris@0 102 Use `isAbsolute()` and `isRelative()` to check whether a path is absolute or
Chris@0 103 relative:
Chris@0 104
Chris@0 105 ```php
Chris@0 106 Path::isAbsolute('C:\Programs\PHP\php.ini')
Chris@0 107 // => true
Chris@0 108 ```
Chris@0 109
Chris@0 110 All four methods internally canonicalize the passed path.
Chris@0 111
Chris@0 112 Finding Longest Common Base Paths
Chris@0 113 ---------------------------------
Chris@0 114
Chris@0 115 When you store absolute file paths on the file system, this leads to a lot of
Chris@0 116 duplicated information:
Chris@0 117
Chris@0 118 ```php
Chris@0 119 return array(
Chris@0 120 '/var/www/vhosts/project/httpdocs/config/config.yml',
Chris@0 121 '/var/www/vhosts/project/httpdocs/config/routing.yml',
Chris@0 122 '/var/www/vhosts/project/httpdocs/config/services.yml',
Chris@0 123 '/var/www/vhosts/project/httpdocs/images/banana.gif',
Chris@0 124 '/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
Chris@0 125 );
Chris@0 126 ```
Chris@0 127
Chris@0 128 Especially when storing many paths, the amount of duplicated information is
Chris@0 129 noticeable. You can use `Path::getLongestCommonBasePath()` to check a list of
Chris@0 130 paths for a common base path:
Chris@0 131
Chris@0 132 ```php
Chris@0 133 $paths = array(
Chris@0 134 '/var/www/vhosts/project/httpdocs/config/config.yml',
Chris@0 135 '/var/www/vhosts/project/httpdocs/config/routing.yml',
Chris@0 136 '/var/www/vhosts/project/httpdocs/config/services.yml',
Chris@0 137 '/var/www/vhosts/project/httpdocs/images/banana.gif',
Chris@0 138 '/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
Chris@0 139 );
Chris@0 140
Chris@0 141 Path::getLongestCommonBasePath($paths);
Chris@0 142 // => /var/www/vhosts/project/httpdocs
Chris@0 143 ```
Chris@0 144
Chris@0 145 Use this path together with `Path::makeRelative()` to shorten the stored paths:
Chris@0 146
Chris@0 147 ```php
Chris@0 148 $bp = '/var/www/vhosts/project/httpdocs';
Chris@0 149
Chris@0 150 return array(
Chris@0 151 $bp.'/config/config.yml',
Chris@0 152 $bp.'/config/routing.yml',
Chris@0 153 $bp.'/config/services.yml',
Chris@0 154 $bp.'/images/banana.gif',
Chris@0 155 $bp.'/uploads/images/nicer-banana.gif',
Chris@0 156 );
Chris@0 157 ```
Chris@0 158
Chris@0 159 `getLongestCommonBasePath()` always returns canonical paths.
Chris@0 160
Chris@0 161 Use `Path::isBasePath()` to test whether a path is a base path of another path:
Chris@0 162
Chris@0 163 ```php
Chris@0 164 Path::isBasePath("/var/www", "/var/www/project");
Chris@0 165 // => true
Chris@0 166
Chris@0 167 Path::isBasePath("/var/www", "/var/www/project/..");
Chris@0 168 // => true
Chris@0 169
Chris@0 170 Path::isBasePath("/var/www", "/var/www/project/../..");
Chris@0 171 // => false
Chris@0 172 ```
Chris@0 173
Chris@0 174 Finding Directories/Root Directories
Chris@0 175 ------------------------------------
Chris@0 176
Chris@0 177 PHP offers the function `dirname()` to obtain the directory path of a file path.
Chris@0 178 This method has a few quirks:
Chris@0 179
Chris@0 180 * `dirname()` does not accept backslashes on UNIX
Chris@0 181 * `dirname("C:/Programs")` returns "C:", not "C:/"
Chris@0 182 * `dirname("C:/")` returns ".", not "C:/"
Chris@0 183 * `dirname("C:")` returns ".", not "C:/"
Chris@0 184 * `dirname("Programs")` returns ".", not ""
Chris@0 185 * `dirname()` does not canonicalize the result
Chris@0 186
Chris@0 187 `Path::getDirectory()` fixes these shortcomings:
Chris@0 188
Chris@0 189 ```php
Chris@0 190 echo Path::getDirectory("C:\Programs");
Chris@0 191 // => C:/
Chris@0 192 ```
Chris@0 193
Chris@0 194 Additionally, you can use `Path::getRoot()` to obtain the root of a path:
Chris@0 195
Chris@0 196 ```php
Chris@0 197 echo Path::getRoot("/etc/apache2/sites-available");
Chris@0 198 // => /
Chris@0 199
Chris@0 200 echo Path::getRoot("C:\Programs\Apache\Config");
Chris@0 201 // => C:/
Chris@0 202 ```
Chris@0 203