How do I properly split a PATH variable in PHP? - php

I want to split
$path = getenv('PATH');
into its components. How do I determine the separator char in an os-dependent fashion?

You can use the PATH_SEPARATOR constant, then the DIRECTORY_SEPARATOR constant to split the path if needed.
See Directory Predefined Constants

Use the PATH_SEPARATOR constant.

I know this works for the include_path - not sure about getenv('PATH'):
$paths = split(PATH_SEPARATOR, getenv('PATH'));

I seem to remember that Windows will accept both forward- and back-slashes as a file-separator, so you may not have to worry about it.

Related

php can't find class [duplicate]

require_once dirname(__FILE__).DIRECTORY_SEPARATOR . './../../../wp-config.php';
require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'inc/options.php';
The above code is from a plugin from the Wordpress.
I don't understand why half of it uses DIRECTORY_SEPARATOR, but the other half uses "/" ?
Because in different OS there is different directory separator. In Windows it's \ in Linux it's /. DIRECTORY_SEPARATOR is constant with that OS directory separator. Use it every time in paths.
In you code snippet we clearly see bad practice code. If framework/cms are widely used it doesn't mean that it's using best practice code.
All of the PHP IO functions will internally convert slashes to the appropriate character, so it's not a huge deal which method you use. Below are some things to consider.
It can look ugly and confusing when you print out your file paths and there is a mix of \ and /. This won't ever happen if DIRECTORY_SEPARATOR is used
Using something such as $generated_css = DIRECTORY_SEPARATOR.'minified.css'; will work all fine and dandy for file IO, but if a developer unknowingly references it in a URL such as echo "<link rel='stylesheet'href='https:​//example.com$generated_css'>";, a bug was just created. Did you catch it? While this will work on Windows, for everyone else a forward slash, instead of a backslash, will be in $generated_css, resulting in the percent encoded, non-existant, URL https://example.com%5cgenerated_css! When using a DIRECTORY_SEPARATOR you have to take special care to make sure your filepath variables never end up in a URL.
And lastly, in the unlikely scenario your filepath is used by non-PHP code — for example, in a shell_exec call — you won't be able to mix slashes and will need to either construct the filepath with DIRECTORY_SEPARATOR or use realpath.
I learned from distributing code that the best way for your application to run on both Linux and Windows is to never use DIRECTORY_SEPARATOR, or backslashes \\, and to ONLY use forward slashes /.
Why? Because a backslash directory separator ONLY works on Windows. And forward slashes works on ALL (Linux, Windows, Mac altogether).
Using the constant DIRECTORY_SEPARATOR or escaping your backslashes \\ quickly becomes messy. I mean look at it:
$file = 'path' . DIRECTORY_SEPARATOR . 'to' . DIRECTORY_SEPARATOR . 'file';
$file = str_replace('/', DIRECTORY_SEPARATOR, 'path/to/file';
$file = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? 'path\\to\\file' : 'path/to/file';
When you can just do this:
$file = 'path/to/file';
The only downside is that on Windows; PHP will return backslashes for all file references from functions like realpath(), glob(), and magic constants like __FILE__ and __DIR__. So you might need to str_replace() them into forward slashes to keep it consistant.
$dir = str_replace('\\', '/', realpath('../'));
I wish there was a php.ini setting to always return forward slashes.
Do not use your own folder separators. Always use DIRECTORY_SEPARATOR, because:
In some special cases you really need the correct path delimiter
The OS might handle it correctly, but many 3rd party applications can't and might fail!
Some operating systems do not use / or \ as separators but something different
Don't forget: Use the constant only on the remote system - don't use it for URIs or anything else that you want to send to the client (except you really need it, like a "remote browser").

Proper path manipulation in PHP

Here are some things I have done in PHP:
$normalizedPath = rtrim($path, '/');
$fullPath = $path . '/' . $basename;
Is there a better class or function to do this where I do not need to hardcode / into my application? Hopefully this will work with unicode and CJK characters.
You should use realpath() function.
Check pathinfo function too, it may be useful
No there are no functions to assemble a path.
Since PHP supports both, the Windows style paths and the UNIX style paths, the rtrim() statement will not work if $path is a Windows style path. You can use realpath() to work around this, but realpath() has the drawback that it returns an absolute path which might be not desired and it returns false for non existing paths, which might be a problem as well in cases were you build a path for something that should be created but does not already exist.

When to use DIRECTORY_SEPARATOR in PHP code?

require_once dirname(__FILE__).DIRECTORY_SEPARATOR . './../../../wp-config.php';
require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'inc/options.php';
The above code is from a plugin from the Wordpress.
I don't understand why half of it uses DIRECTORY_SEPARATOR, but the other half uses "/" ?
Because in different OS there is different directory separator. In Windows it's \ in Linux it's /. DIRECTORY_SEPARATOR is constant with that OS directory separator. Use it every time in paths.
In you code snippet we clearly see bad practice code. If framework/cms are widely used it doesn't mean that it's using best practice code.
All of the PHP IO functions will internally convert slashes to the appropriate character, so it's not a huge deal which method you use. Below are some things to consider.
It can look ugly and confusing when you print out your file paths and there is a mix of \ and /. This won't ever happen if DIRECTORY_SEPARATOR is used
Using something such as $generated_css = DIRECTORY_SEPARATOR.'minified.css'; will work all fine and dandy for file IO, but if a developer unknowingly references it in a URL such as echo "<link rel='stylesheet'href='https:​//example.com$generated_css'>";, a bug was just created. Did you catch it? While this will work on Windows, for everyone else a forward slash, instead of a backslash, will be in $generated_css, resulting in the percent encoded, non-existant, URL https://example.com%5cgenerated_css! When using a DIRECTORY_SEPARATOR you have to take special care to make sure your filepath variables never end up in a URL.
And lastly, in the unlikely scenario your filepath is used by non-PHP code — for example, in a shell_exec call — you won't be able to mix slashes and will need to either construct the filepath with DIRECTORY_SEPARATOR or use realpath.
I learned from distributing code that the best way for your application to run on both Linux and Windows is to never use DIRECTORY_SEPARATOR, or backslashes \\, and to ONLY use forward slashes /.
Why? Because a backslash directory separator ONLY works on Windows. And forward slashes works on ALL (Linux, Windows, Mac altogether).
Using the constant DIRECTORY_SEPARATOR or escaping your backslashes \\ quickly becomes messy. I mean look at it:
$file = 'path' . DIRECTORY_SEPARATOR . 'to' . DIRECTORY_SEPARATOR . 'file';
$file = str_replace('/', DIRECTORY_SEPARATOR, 'path/to/file';
$file = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? 'path\\to\\file' : 'path/to/file';
When you can just do this:
$file = 'path/to/file';
The only downside is that on Windows; PHP will return backslashes for all file references from functions like realpath(), glob(), and magic constants like __FILE__ and __DIR__. So you might need to str_replace() them into forward slashes to keep it consistant.
$dir = str_replace('\\', '/', realpath('../'));
I wish there was a php.ini setting to always return forward slashes.
Do not use your own folder separators. Always use DIRECTORY_SEPARATOR, because:
In some special cases you really need the correct path delimiter
The OS might handle it correctly, but many 3rd party applications can't and might fail!
Some operating systems do not use / or \ as separators but something different
Don't forget: Use the constant only on the remote system - don't use it for URIs or anything else that you want to send to the client (except you really need it, like a "remote browser").

dirname(__FILE__) showing backslashes

I have a config file in my base directory and I'm trying to figure the absolute path to the directory to use for file includes. However windows is using backslashes in the path.
define( 'ABSOLUTE_PATH', dirname(__FILE__));
include( ABSOLUTE_PATH . "/includes/include.php" );
Using this method it returns this path...
C:\xampp\htdocs\websites/includes/include.php
As you can see it is a mix of forward slashes and backslashes.
What is the best way for fixing this problem, or is there a better method that I can find the absolute path?
EDIT:
The reason I would like it to use a forward slash is I am serializing the results to be stored in a database. Backslashes are removed when serialized. :)
You should be using the DIRECTORY_SEPARATOR constant:
include( ABSOLUTE_PATH . DIRECTORY_SEPARATOR . "includes" . DIRECTORY_SEPARATOR . "include.php" );
Using DIRECTORY_SEPARATOR is unnecessary in your example. As long as you use the forward slash, “/”, you’ll be OK. Windows doesn’t mind it, and it’s best for *nix operating systems.
Note that DIRECTORY_SEPARATOR is useful for things like explode-ing a path that the system gave you.
From https://alanhogan.com/tips/php/directory-separator-not-necessary
str_replace("\\","/",dirname(FILE)); works for me... (note double "\\" for scape the 2nd "\")

Slashes and backslashes uniformity on UNIX / Windows

I'm writing a PHP class, and I want it to be cross-platform compatible. I need to explode a path to find a particular folder name. What do I choose for the delimiter? The path will contain '/' on UNIX and '\' on Windows.
In this particular example, I want to get the name of the directory where an included file is stored. I use this :
private function find_lib_dir() {
$array_path = explode('/', __DIR__);
return $array_path[count($array_path)-1];
}
In this situation (and more generally), what can I do to make sure it will work on both Windows and UNIX?
Thanks!
You can use DIRECTORY_SEPARATOR as follows:
$array_path = explode(DIRECTORY_SEPARATOR, __DIR__);
Use basename() and dirname() for path manipulation instead of parsing it yourself.
I would do something like this:
private function find_lib_dir() {
// convert windows backslashes into forward slashes
$dir = str_replace("\\", "/", __DIR__);
$array_path = explode('/', $dir);
return $array_path[count($array_path)-1];
}
For your particular example, you could do what the other answers provided. However, if you are building strings yourself like:
__DIR__ . '/path/to/dir';
And then try to explode it, then you will have issues on UNIX vs Windows systems. In this situation, it would be best (imo) to replace all the backslashes to forward slashes (which is supported on both systems). And then explode based on forward slash.
You should use the DIRECTORY_SEPARATOR constant

Categories