Both the following lines of calling name spaced method work, are there any case which single slash does not work?
<?php
namespace Foo\Bar;
class Dummy {
public static function hello() {
echo 'world';
}
}
echo \Foo\Bar\Dummy::hello();
call_user_func('\Foo\Bar\Dummy::hello');
call_user_func('\\Foo\\Bar\\Dummy::hello');
The reason I ask is: If single slash always work, why I see so many of double slash in the Internet, even the composer generate file like this [1]? Are there any case I am missing?
[1] https://github.com/ircmaxell/quality-checker/blob/master/vendor/composer/autoload_namespaces.php
Any literal notation works as is with a single backslash, that's how the syntax is defined:
namespace Foo\Bar;
echo \Foo\Bar\Dummy::hello();
When using strings, string escaping rules apply:
call_user_func('Foo\Bar\Dummy::hello');
call_user_func('Foo\\Bar\\Dummy::hello');
(BTW, don't start with a backslash in these cases, fully qualified class names in strings are always absolute, you don't need the starting backslash to resolve relative namespace references.)
In single quoted strings, only a single character needs to be escaped: '. I.e. if you want to write a single quote in single quotes, you need to escape it with a backslash:
echo 'don\'t';
That makes the backslash a special character, which you may need to escape as well:
echo 'backslash: \\';
So, in single quoted strings, \\ is always a single backslash. If you're using a single backslash and the next character is not a ' or \, then that single backslash is also just a single backslash:
echo 'just \ a \ backslash';
So except for those two cases, it makes no difference.
Double quoted strings have a lot more escape sequences like \n, which you'd need to take care of.
BTW, that's why many people were pretty unhappy with the choice of \ as a namespace separator, because it's already a character with a special meaning and leads to confusion and possibly bugs.
Within single quoted strings you only really need to use a backslash to escape a single quote or a backslash if it appears as the last character, e.g. 'foo\\'.
In your example, this line highlights this exact case:
'Symfony\\Component\\Routing\\' => $vendorDir . '/symfony/routing/',
^^
This incidentally is also the output of var_export():
$a = ['foo\bar\baz\\' => 'foo'];
var_export($a);
array (
'foo\\bar\\baz\\' => 'foo',
)
So even though it's technically not necessary to escape the other backslashes in the above example, var_export() will do this anyway.
See also: Strings and var_export()
In PHP, special characters don't need to be escaped when using single quotes [' ']. Most programming languages check things for \t (tab), \n (new line), \r (carriage return), and others when using double quotes [" "]. When you use double quotes in PHP, it searches for these, so you have to escape the special backslash character so PHP knows you're not escaping the character after the backslash. This is not the case with single quotes.
You can test this yourself:
echo "this\tis\ta\ttest";
echo 'this\tis\ta\ttest';
Related
Do I need to escape backslash in PHP?
echo 'Application\Models\User'; # Prints "Application\Models\User"
echo 'Application\\Models\\User'; # Same output
echo 'Application\Model\'User'; # Gives "Application\Model'User"
So it's an escape character. Shouldn't I need to escape it (\) if I want to refer to Application\Models\User?
In single quoted strings only the escape sequences \\ and \' are recognized; any other occurrence of \ is interpreted as a plain character.
So since \M and \U are no valid escape sequences, they are interpreted as they are.
In single quoted strings, it's optional to escape the backslash, the only exception is when it's before a single quote or a backslash (because \' and \\ are escape sequences).
This is common when writing regular expressions, because they tend to contain backslashes. It's easier to read preg_replace('/\w\b/', ' ', $str) than /\\w\\b/.
See the manual.
Since your last example contains a quote ('), you need to escape such strings with the addslashes function or simply adding a slash yourself before it like this:
'Application\Model\\'User'
You will find the complete explanation here:
http://nl.php.net/manual/en/language.types.string.php
I think it depends on the context, but it is a good idea to escape backslashes if using it in file paths.
Another good idea is to assign the directory separator to a constant, which I've seen done in various applications before, and use it as thus:
<?php
define('DIRECTORY_SEPARATOR', '\\');
echo 'Application'.DIRECTORY_SEPARATOR . 'Models' . DIRECTORY_SEPARATOR . 'User';
?>
If you wish to save space and typing, others use DS for the constant name.
<?php
define('DS', '\\');
echo 'Application'.DS.'Models'.DS.'User';
?>
This keeps your application portable if you move from a Windows environment to a *nix environment, as you can simple change the directory separator constant to a forward slash.
If it is to be used in an HTML page, then you might as well use HTML character code \ to represent a backslash, like so:
echo 'Application\Models\User';
It will print:
Application\Models\User
Reference:
https://ascii.cl/htmlcodes.htm
I'm using PHP 7.1.11
As mentioned in the PHP manual
To specify a literal single quote in a string which is already
enclosed in a pair of single quotes, escape it with a backslash ().
To specify a literal backslash, double it (\). All other instances of
backslash will be treated as a literal backslash: this means that the
other escape sequences you might be used to, such as \r or \n, will be
output literally as specified rather than having any special meaning.
I'm not understanding the above paragraph due to which following doubts have been created in my mind :
Can only single quotes be specified in a string(using the escape sequence character \') already enclosed in single quotes?
Consider the below sentence
To specify a literal backslash, double it (\).
Actually, I can simply specify a single backslash literal by adding single \ in a string which is already enclosed in a pair of single quotes then why the manual is saying that I have to use double slash(\\) to specify it?
Now consider the below sentence
All other instances of
backslash will be treated as a literal backslash: this means that the
other escape sequences you might be used to, such as \r or \n, will be
output literally as specified rather than having any special meaning.
Does this mean that no other escape sequence character except the single quote(\') can be added in a string quoted in single quotes? Will the characters like \r, \t and \n will get printed as it is like a simple text in a browser?
Someone please clarify all of my above doubts.
Thanks.
Regarding "first paragraph", it's about escaping backslash right before your escaped single quote
echo '\\\'' // Output: \'
All other backslashes output as it is, so there is no possibility to write "new line" symbol with single quotes.
echo '\n\ \'' // Output: \n\ '
To match a literal backslash, many people and the PHP manual say: Always triple escape it, like this \\\\
Note:
Single and double quoted PHP strings have special meaning of backslash. Thus if \ has to be matched with a regular expression \\, then "\\\\" or '\\\\' must be used in PHP code.
Here is an example string: \test
$test = "\\test"; // outputs \test;
// WON'T WORK: pattern in double-quotes double-escaped backslash
#echo preg_replace("~\\\t~", '', $test); #output -> \test
// WORKS: pattern in double-quotes with triple-escaped backslash
#echo preg_replace("~\\\\t~", '', $test); #output -> est
// WORKS: pattern in single-quotes with double-escaped backslash
#echo preg_replace('~\\\t~', '', $test); #output -> est
// WORKS: pattern in double-quotes with double-escaped backslash inside a character class
#echo preg_replace("~[\\\]t~", '', $test); #output -> est
// WORKS: pattern in single-quotes with double-escaped backslash inside a character class
#echo preg_replace('~[\\\]t~', '', $test); #output -> est
Conclusion:
If the pattern is single-quoted, a backslash has to be double-escaped \\\ to match a literal \
If the pattern is double-quoted, it depends whether
the backlash is inside a character-class where it must be at least double-escaped \\\
outside a character-class it has to be triple-escaped \\\\
Who can show me a difference, where a double-escaped backslash in a single-quoted pattern e.g. '~\\\~' would match anything different than a triple-escaped backslash in a double-quoted pattern e.g. "~\\\\~" or fail.
When/why/in what scenario would it be wrong to use a double-escaped \ in a single-quoted pattern e.g. '~\\\~' for matching a literal backslash?
If there's no answer to this question, I would continue to always use a double-escaped backslash \\\ in a single-quoted PHP regex pattern to match a literal \ because there's possibly nothing wrong with it.
A backslash character (\) is considered to be an escape character by both PHP's parser and the regular expression engine (PCRE). If you write a single backslash character, it will be considered as an escape character by PHP parser. If you write two backslashes, it will be interpreted as a literal backslash by PHP's parser. But when used in a regular expression, the regular expression engine picks it up as an escape character. To avoid this, you need to write four backslash characters, depending upon how you quote the pattern.
To understand the difference between the two types of quoting patterns, consider the following two var_dump() statements:
var_dump('~\\\~');
var_dump("~\\\\~");
Output:
string(4) "~\\~"
string(4) "~\\~"
The escape sequence \~ has no special meaning in PHP when it's used in a single-quoted string. Three backslashes do also work because the PHP parser doesn't know about the escape sequence \~. So \\ will become \ but \~ will remain as \~.
Which one should you use:
For clarity, I'd always use ~\\\\~ when I want to match a literal backslash. The other one works too, but I think ~\\\\~ is more clear.
There is no difference between the actual escaping of the slash in either single or double quoted strings in PHP - as long as you do it correct. The reason why you're getting a WONT WORK on your first example is, as pointed out in the comments, it expands \t to the tab meta character.
When you're using just three backslashes, the last one in your single quoted string will be interpreted as \~, which as far as single quoted strings go, will be left as it is (since it does not match a valid escape sequence). It is however just a coincidence that this will be parsed as you expect in this case, and not have some sort of side effect (i.e, \\\' would not behave the same way).
The reason for all the escaping is that the regular expression also needs backslashes escaped in certain situations, as they have special meaning there as well. This leads to the large number of backslashes after each other, such as \\\\ (which takes eight backslashes for the markdown parser, as it yet again adds another level of escaping).
Hopefully that clears it up, as you seem to be confused regarding the handling of backslashes in single/double quoted strings more than the behaviour in the regular expression itself (which will be the same regardless of " or ', as long as you escape things correctly).
I was looking for a solid article on when double escaping is necessary and when it is not, but I was not able to find anything. Perhaps I didn't look hard enough, because I'm sure there is an explanation out there somewhere, but lets just make it easy to find for the next guy that has this question!
Take for example the following regex patterns:
/\n/
/domain\.com/
/myfeet \$ your feet/
Nothing ground breaking right? OK, lets use those examples within the context of PHP's preg_match function:
$foo = preg_match("/\n/", $bar);
$foo = preg_match("/domain\.com/", $bar);
$foo = preg_match("/myfeet \$ your feet/", $bar);
To my understanding, a backslash in the context of a quoted string value escapes the following character, and the expression is being given via a quoted string value.
Would the previous be like doing the folloing, and wouldnt this cause an error?:
$foo = preg_match("/n/", $bar);
$foo = preg_match("/domain.com/", $bar);
$foo = preg_match("/myfeet $ your feet/", $bar);
Which is not what I want right? those expressions are not the same as above.
Would I not have to write them double escaped like this?
$foo = preg_match("/\\n/", $bar);
$foo = preg_match("/domain\\.com/", $bar);
$foo = preg_match("/myfeet \\$ your feet/", $bar);
So that when PHP processes the string it escapes the backslash to a backslash which is then left in when its passed to the PCRE interpreter?
Or does PHP just magically know that I want to pass that backslash to the PCRE interpreter... i mean how does it know I'm not trying to \" escape a quote that I want to use in my expression? or are only double slashes required when using an escaped quote? And for that matter, would you need to TRIPLE escape a quote? \\\" You know, so that the quote is escaped and a double is left over?
Whats the rule of thumb with this?
I just did a test with PHP:
$bar = "asdfasdf a\"ONE\"sfda dsf adsf me & mine adsf asdf asfd ";
echo preg_match("/me \$ mine/", $bar);
echo "<br /><br />";
echo preg_match("/me \\$ mine/", $bar);
echo "<br /><br />";
echo preg_match("/a\"ONE\"/", $bar);
echo "<br /><br />";
echo preg_match("/a\\\"ONE\\\"/", $bar);
echo "<br /><br />";
Output:
0
1
1
1
So, it looks like somehow it doesnt really matter for quotes, but for the dollar sign, a double escape is required as I thought.
Double quoted strings
When it comes to escaping inside double quotes, the rule is that PHP will inspect the character(s) immediately following the backslash.
If the neighboring character is in the set ntrvef\$" or if a numeric value follows it (rules can be found here) it gets evaluated as the corresponding control character or ordinal (hexadecimal or octal) representation, respectively.
It's important to note that if an invalid escape sequence is given, the expression is not evaluated and both the backslash and character remain. This is different from some other languages where an invalid escape sequence would cause an error instead.
E.g. "domain\.com" will be left as is.
Note that variables get expanded inside double quotes as well, e.g. "$var" needs to be escaped as "\$var".
Single quotes strings
Since PHP 5.1.1, any backslash inside single quoted strings (and followed by at least one character) will get printed as is and no variables get substituted either. This is by far the most convenient feature of single quoted strings.
Regular expressions
For escaping regular expressions, it's best to leave escaping to preg_quote():
$foo = preg_match('/' . preg_quote('mine & yours', '/') . '/', $bar);
This way you don't have to worry about which characters need to be escaped, so it works well for user input.
See also: preg_quote
Update
You added this test:
"/me \$ mine/"
This gets evaluated as "/me $ mine/"; but in PCRE the $ has a special meaning (it's an end-of-subject anchor).
"/me \\$ mine/"
This is evaluated as "/me \$ mine/" and so the backslashes is escaped for PHP itself whereas the $ is escaped for PCRE. This only works by accident btw.
$var = 'something';
"/me \\$var mine/"
This gets evaluated as "/me \something", so you need to escape the $ again.
"/me \\\$var mine/"
Use single quotes. They prevent escape sequences from occurring.
For example:
php > print "hi\n";
hi
php > print 'hi\n';
hi\nphp >
Whenever you have an invalid escape sequence, PHP actually leaves the characters literally in the string. From the documentation:
As in single quoted strings, escaping any other character will result in the backslash being printed too.
I.e. "\&" really is interpreted as "\&". There are not that many escape sequences, so in most cases you probably get away with a single backslash. But for consistency, escaping the backslash might be a better choice.
As always: Know what you are doing :)
OK So I did some more testing and discovered the RULE OF THUMB when encapsulating a PCRE in DOUBLE QUOTES, the following holds true:
$ - Requires double escape because PHP will interpret that as the beginning of a variable if text is immediately following it. Left unescaped and it will indicate the end of your needle and will break.
\r\n\t\v - Special PHP string escapes, single escape required only.
[\^$.|?*+() - Special RegEx characters, require single escape only. Double escape does not seem to break expressions when used unnecessarily.
" - Quotes are obviously going to have to be escaped due to the encapsulation, but only need to be escaped once.
\ - Searching for a backslash? Using the double quote encapsulation of your expression, this will require 3 escapes! \\ (four backslashes in total)
Anything I'm missing?
I'll start saying that all I'll write below is not exactly what happens, but, for clarity, I'll simplify it.
Imagine that there are two evaluations happening when using regular expressions: the first being done by PHP and the second being done by PCRE, as if they were separate engines. And for our bad luck,
PHP AND PCRE EVALUATES THINGS IN DIFFERENT WAYS.
We have 3 "guys" here: 1) the USER; 2) the PHP and; 3) the PCRE.
The USER communicates with PHP by writing the CODE, which is exactly what you type in a code editor.
PHP then evaluates this CODE and sends another bit of information to PCRE. This bit of information is different from what you typed in your CODE.
PCRE then evaluates it and returns something to PHP, that evaluates this response and returns something to the USER.
I'll explain better in the exemple below. There I'm going to use the backslash ("\") to ilustrate what's going on.
Assume this bit of CODE in a php file:
<?php
$sub = "A backslash \ in a string";
$pat1 = "#\#";
$pat2 = "#\\#";
$pat3 = "#\\\#";
$pat4 = "#\\\\#";
echo "sub: ".$sub;
echo "\n\n";
echo "pat1: ".$pat1;
echo "\n";
echo "pat2: ".$pat2;
echo "\n";
echo "pat3: ".$pat3;
echo "\n";
echo "pat4: ".$pat4;
?>
This will print:
sub: A backslash \ in a string
pat1: #\#
pat2: #\#
pat3: #\\#
pat4: #\\#
In this exemple, there is no regular expression involved, so there is only the PHP evaluation of the code happening.
PHP leaves a backslash as is if it doesn't precede any special character. That's why it prints the backslash correctly in $sub.
PHP evaluates $pat1 and $pat2 EXACTLY the same, because in $pat1 the backslash is left as is, and in $pat2 the first backslash escapes the second, resulting in a single backslash.
Now, in $pat3, the first backslash escapes the second, resulting in one backslash. Then PHP evaluates the third backslash and leaves it as is because it is not preceding anything special. The result is going to be the double backslash.
Now someone could say "but now we have two backslashes again! shouldn't the first one escape the second one again?!"
The answer is "No". After PHP evaluates the first two backslashes into a single one, it doesn't look back again, and keeps moving on evaluating what is next.
At this point you already know what's going on with $pat4: the first backslash escapes the second and the third escapes the fourth, leaving two in the end.
Now that it's clear what PHP is doing to these strings, let's add some more code after the previous one.
if (preg_match($pat1, $sub)) echo "test1: true"; else echo "test1: false";
echo "\n";
if (preg_match($pat2, $sub)) echo "test2: true"; else echo "test2: false";
echo "\n";
if (preg_match($pat3, $sub)) echo "test3: true"; else echo "test3: false";
echo "\n";
if (preg_match($pat4, $sub)) echo "test4: true"; else echo "test4: false";
And the result is:
test1: false
test2: false
test3: true
test4: true
So, what's going on here is that PHP is not sending "what you typed" in the CODE directly to PCRE. Instead, PHP is sending what it has evaluated previously (which are exactly what we saw above).
For test1 and test2, even though we have written different patterns in the CODE for each test, PHP is sending the same pattern #\# to PCRE. The same thing happens for test3 and test4: PHP is sending #\\#. So, the results for test1 and test2 are the same, as well as for test3 and test4.
Now, what's going on when PCRE evaluates these patterns? PCRE doesn't act like PHP.
In test1 and test2, when PCRE sees a single backslash escaping nothing special (or nothing at all), it doesn't leave it as is. Instead, it problably thinks "what the hell is this?" and returns an error to PHP (actually, I don't really know what goes on when sending a single backslash to PCRE, searched for this, but still no conclusive). Then PHP takes what we are assuming is an error and evaluates it as "false" and returns that to the rest of the CODE (in this exemple, the if () function).
In test3 and test4, things go as we now expect: PCRE evaluates the first backslash as escaping the second, resulting in a single backslash. That of course matches the $sub string and returns a "successful message" to PHP, which evaluates it as "true".
ANSWERING QUESTIONS
Some characters are special to PHP (e.g. n for NEW LINE, t for TAB).
Some characters are special to PCRE (e.g. . (dot) to match any character, s to match whitespaces).
And some characters are special to both (e.g. $ to php is the beginning of the name of a variable and to PCRE it asserts the end of the subject).
That's why you need to escape newlines just once, like this \n. PHP will evaluate it as the REAL character NEW LINE and send that to PCRE.
For the dot, if you want to match that specific character, you should use \. and PHP will do nothing because the dot isn't a special character to PHP in a string. Instead, it will send them as is to PCRE. Now on PCRE, it will "see" a backslash preceding a dot and understand that it should match that specific character. If you use a double escape \\. the first backslash will escape the second, leaving you with the same result.
And if you want to match a dollar sign in a string, then you should use \\\$. In PHP, the first backslash will escape the second one, leaving a single backslash. Then the third backslash will escape the dollar sign. In the end, the result is \$. This is what PCRE will receive. PCRE will see that backslash and understand that the dollar sign is not asserting end of subject, but the literal character.
QUOTES
And now we've come to quotes. The problem with them is the fact that PHP evaluates a string in different ways, depending on the quotes used to surround it. Check it out: Strings
All I said until this point is valid for double quotes.
If you try this '\n' in single quotes, PHP will evaluate that backslash as a literal one.
But, if it is used in a regular expression, PCRE will get this string as is. And since n is also special to PCRE, it will interpret that as a newline character, and BOOM, it "magicaly" matches a newline in a string.
Check the escape sequences here: Escape Sequences
As I said in the beginning, things area not exactly as I tried to explain here, but I really hope it helps (and not make it more confusing than it already is).
I have double backslashes '\' in my string that needs to be converted into single backslashes '\'. I've tried several combinations and end up with the whole string disappearing when I used echo or more backslashes are added to the string by accident. This regex thing is making me go bonkers...lol...
I tried this amongst other failed attempts:
$pattern = '[\\]';
$replacement = '/\/';
?>
<td width="100%"> <?php echo preg_replace($pattern, $replacement,$q[$i]);?></td>
I do apologise if this is a foolish issue and I appreciate any pointers.
Use stripslashes() - it does exactly what you're looking for.
<td width="100%"> <?php echo stripslashes($q[$i]);?></td>
Use stripslashes instead. Also, in your regex, you are searching for single backslashes and your replacement is incorrect. \\{2} should search for double backslashes and \ should replace them with singles, although I haven't tested this.
Just to explain further, the pattern [\\] matches any character in a set comprised of a single backslash. In php, you should also delimit your regex with forward slashes: /[\\]/
Your replacement, which is (without delimiters) \, is not a regular expression for matching a single backslash. The regex for matching a single backslash is \\. Note the escaping. This said, the replacement term needs to be a string, not a regex (with the exception of backreferences).
EDIT: Sven claims below that stripslashes removes all backslashes. This is simply not true, and I will explain why below.
If a string contains 2 backslashes, the first one will be considered an escaping backslash and will be removed. This can be seen at http://www.phpfiddle.org/main/code/3yn-2ut. The fact that any backslashes remain at all by itself contradicts the claim that stripslashes removes all backslashes.
Just to clarify, this string declaration is invalid: $x = "\";, since the backslash escapes the second quote. This string "\\" contains one backslash. In the process of unquoting this string, this backslash will be removed. This "\\\\" string contains two backslashes. When unquoting, the first will be considered an escaping backslash, and will be removed.
Use preg_replace to turn double backslash into single backslash:
preg_replace('/\\\\{2}/', '\\', $str)
The \ in the first parameter needs to be escaped twice, once for string and once more for regex, just like CodeAngry says.
In the second parameter it only gets excaped once for string.
Make sense?
Never use a regular expression if the string you are looking for is constant, as is the case with "Every instance of double backslash".
Use str_replace() for this task. It is a very easy function that replaces every occurance of a string with another.
In your case: str_replace('\\\\', '\\', $var).
The double backslash actually translates into four backslashed, because inside any quotes (single or double), a single backslash is the start of an escape sequence for the following character. If you want one literal backslash, you have to write two of them. You want two backslashes, you have to write four of them.
I do not like the suggestion of stripslashes(). This will of course "decode" your double backslash into one single backslash. But it will also remove all single backslashes in the whole string. If there were none - fine, otherwise things will fail now.
$pattern = '[\\]'; // wrong
$pattern = '[\\\\]'; // right
escape \ as \\ and escape \\ as \\\\ because \\] means escaped ].
Use htmlentities function to convert your slashes to html entities then using str_replace or preg_match to change them with new entity