When writing out filepaths and URLs, should you use forward slashes
/ or backslashes
\? Windows expects one, whereas Unix-style operating systems (Linux and Mac OSs, primarily) expect another. PHP has two built-in solutions, but both have problems, especially if you’re working with WordPress.
At work, I’ve recently had some trouble getting my linux virtual machine VVV to work and so have been trying out a different system that runs my development websites directly on my Windows operating system, Laragon.
It’s been quite a while since any of us at Event Espresso have ran our code on a Windows machine directly, so there were a few problems, chiefly that Windows uses backslashes,
\, to separate folders, whereas Unix-style operating systems use forward slashes,
This meant that some unit test code expected to find forward slashes, and when it found backslashes, reported an error.
This forward-or-backslashes problem occurs a little when you’re writing code that will only ever run on one machine. But the problem gets worse if the code will be distributed and could be run anywhere. Plus, if you’re writing code that works with WordPress, there are a few more considerations.
So, on Windows machines, the path to a file will look something like this:
path\to\file.php, whereas on Unix-style operating systems (even if they’re a virtual machine, like VVV), the paths instead look like
This isn’t a new problem, by any means, and the programming language PHP has given us two different attempts to fix it, but each has problems. Let me tell what the options are, then their problems.
There is a constant called
DIRECTORY_SEPARATOR, which is
/ on Unix-style operating systems, and it’s
\ on Windows machines. (I suppose a Windows 10 machine using the Linux subsystem will emulate Linux and so use
So, theoretically, your PHP code can just use
DIRECTORY_SEPARATOR in paths, and you’ll be ok. Eg instead of
path\to\file.php, you would do
'path' . DIRECTORY_SEPARATOR . 'to' . DIRECTORY_SEPARATOR . 'file.php'. But there’s another option…
Also, importantly, when writing PHP code, you can always use forward slashes in paths, even for code that runs on a Windows machine. So, no need to use the
DIRECTORY_SEPARATOR constant anyways. Just always use forward slashes, like your paths are all for Unix-style operating systems. Eg just always do
path/to/file.php. Couldn’t be easier, right? Actually, you may be surprised, this Kaiju isn’t quite dead yet…
If you use either
DIRECTORY_SEPARATOR or always use forward slashes, there are a few problems and mistakes you can make. Meaning neither one is perfect.
- Obviously it’s a lot more typing
path . DIRECTORY_SEPARATOR . 'to' . DIRECTORY_SEPARATOR . 'file.php'is way longer than
path/to/file.php. Not only does this actually get exhausting, it’s pretty easy to mistype and add a bug.
- You need to remember that the directory separator in filepaths on a computer/server differ depending on the operating system, but paths in URLs to webpages, no matter which operating systems are in use, should use
/. So, when writing out a path, you’ll always need to ask yourself “Is this a filepath on the computer running the code? Or is this a path that will go into a URL pointing to another website?” It’s easy to get mixed up.
- If you do use
DIRECTORY_SEPARATORin a URL, and that URL is passed into WordPress’ functions
wp_enqueue_style, it will remove the backslash and so breaks the URL. (Note for completeness: web browsers are, of themselves, pretty forgiving – if you give them the wrong slash, they’ll fix it automatically for you. But that doesn’t help if WordPress has already removed the slash entirely).
- WordPress core mostly doesn’t use
DIRECTORY_SEPARATOR, it always uses forward slash
/. This means, if your code is running as a WordPress plugin (like ours) or a theme, even though your code uses
DIRECTORY_SEPARATOR, WordPress’ probably won’t, and so paths will still use a mix of forward and backslashes. This can be onerous because your code and unit tests need to expect either type of slash.
So if your code isn’t working with WordPress, using
DIRECTORY_SEPARATOR is just more typing and you need to know if the path is part of a directory path or a URL. Otherwise, it’s good because filepaths always use
DIRECTORY_SEPARATOR, which is nice and predictable.
- On Windows machines, PHP’s built-in functions and constants use
\. Eg using
__FILE__from within a file will always return
path\to\file.php, regardless of which slashes you decide to type into your code. That means no matter how much you try to “just always use forward slashes”, PHP has already foiled your plans: paths in your code will still be a mix of forward and backslashes. This inconsistency gets a bit sore on the eyes.
- Just like problem #4 with using the
DIRECTORY_SEPARATOR, your code needs to expect both types of slashes in filepaths. That’s again onerous in unit tests and parsing filepaths.
So the list of problems using forward slashes is shorter, at least if you’re using WordPress.
If your using WordPress, you’re probably best always using forward slashes. It’s consistent with WordPress, easier to type, and doesn’t require asking yourself “is this part of a filepath or a URL?”; your code will just need to realize PHP’s built-in functions use
DIRECTORY_SEPARATOR, whereas WordPress’ functions use
/, so your code needs to expect both types of slashes will be used as directory separators. That’s pretty easy to deal with. Just do
str_replace('\\', '/', $filepath);.
Update: In WordPress, it’s actually even easier: do
wp_normalize_path(), like documented on developer.wordpress.org. Although, if you’re writing code for a distributed plugin or theme, you should always be using it, regardless of whether you yourself are on a Windows machine. Thanks @wpscholar for the tip!
If you’re not using WordPress, (or my WordPress trac ticket to use
DIRECTORY_SEPARATOR gets accepted) I’d use
DIRECTORY_SEPARATOR. You’ll be able to rely on filepaths always using the operating system’s slash-of-choice in unit tests and filepath parsing. If your fingers get tired of typing it out, you can create your own constant like
DS as a short-hand for it.
Did I get it right? Does it not make sense? Please leave a comment.