Strings
parse_str()
without Result Argument
PHP makes accessing HTTP GET and POST variables very convenient by creating so-called super-global variables automatically. From a design point of view, using global variables is rather problematic, which is why most frameworks wrap the super-global variables in request objects (or inject their values into request objects) that then get passed around.
The parse_str()
function parses a string containing
URL parameters into an array:
parse_str('name=value', $results);
var_dump($results);
The result is
array(1) {
'name' => string(5) "value"
}
just like you would expect when appending
?name=value
to a URL.
Now, do you still remember the Register Globals mess? In the early days, PHP had a feature called Register Globals that would automatically create global variables from every URL parameter, POST data, and even cookies. The original intent of that functionality had been to make form processing easier. For every non-trivial case, however, trouble ensued, because there are multiple sources of data that all get merged into one set of variables. In other words, POST data might overwrite GET data, or vice versa, depending on the order of processing.
In real life, this feature was one big mess, and it led to
several really bad security problems. To create a perfect disaster,
the order in which PHP processes the various input sources was
configurable in php.ini
, so that as a developer, you
could not rely on anything. Register Globals was at some point made
optional, with PHP putting the data from each input source into one
super-global variable. Register Globals was finally removed from PHP
in version 5.4.
Well, using parse_str()
, before PHP 7.2, you could
still get a lot of what Register Globals had given you – in a
negative sense! Look at what PHP does when you leave out the second
parameter:
parse_str('name=value');
var_dump($name);
Indeed, PHP registers a global variable for you when you do not specify an array to put the data into:
string(5) "value"
This is really bad, and nobody should ever use it! Luckily, toady the above script will complain to you:
Deprecated:
parse_str(): Calling parse_str() without
the result argument is deprecated in ...
If you see this, make sure to get rid of it quickly, your application might have serious security issues due to possible variable injections from the outside.
String Search and Non-String Needles
Passing an argument that is not of type string
to
the following string search functions is deprecated:
strpos()
strrpos()
stripos()
strripos()
strstr()
strchr()
strrchr()
stristr()
Needle arguments that are not of type string
will be
interpreted as a string instead of an ASCII codepoint in the future.
Depending on the intended behavior, non-string needles should be be
cast explicitly cast to string
or the
chr()
function should be used to generate a string from
a number.
Curly Brace Syntax
Curly brace syntax for accessing string offsets has been deprecated:
$string = 'string';
var_dump($string{1});
Executing the code shown above will print the output shown below:
PHP Deprecated: Array and string offset access syntax
with curly braces is deprecated in ...
string(1) "t"
Simply use $string[1]
instead of
$string{1}
to get rid of the deprecation warning.
Concatenation Precedence
Unparenthesized concatenation together with addition or subtraction is now deprecated:
print 'string ' . 1 + 2;
Executing the code shown above with PHP 7.4 prints the output shown below:
PHP Deprecated: The behavior of unparenthesized expressions containing
both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher
precedence in ...
PHP Warning: A non-numeric value encountered in ...
2
PHP 7 evaluates 'string ' . 1 + 2
from left to
right, meaning that 'string ' . 1
is performed first
followed by 'string 1' + 2
. This explains the
non-numeric value encountered
warning in the output
shown above.
Deprecate
hebrevc()
Hebrew is written and read from right to left. With all modern
browsers supporting HTML’s dir
attribute that allows to
specify the text direction (valid values are ltr
for
left-to-right, rtl
for right-to-left, and
auto
for the daring), dealing with reversing strings at
the PHP level should not be necessary any more when generating HTML
output, but it might still come in handy when dealing with CLI
output.
The function hebrevc()
works like
hebrev()
in that it tries to reverse the order of
Hebrew characters, trying not to wrap words. However, in addition to
hebrev()
, it also converts newline characters
(\n
) to <br>
tags.
Since there is clearly no need for a special function to perform
a simple str_replace()
operation,
hebrevc()
has been deprecated.
var_dump(hebrevc("...\n..."));
PHP Deprecated:
Function hebrevc() is deprecated in ...
string(13) "...<br />
..."
Believe it or not, we tried to use Hebrew characters in this
example, but this broke our PDF build, so we had to replace them
with dots. Well, just because we cannot deal with Hebrew characters,
this does not mean that PHP cannot. After all, the function
hebrev()
is still available and not deprecated:
var_dump(hebrevc("...\n..."));
string(7) "...
..."
Deprecate
convert_cyr_string()
The function convert_cyr_string()
converts strings
in one cyrillic character set into another. Just like with
hebrevc()
, we can unfortunately not show an example,
since that would also breaks our PDF build. However, if your
application should rely on convert_cyr_string()
, you
can switch to using the character set conversion functions that the
iconv
extension offers.
Deprecate
FILTER_SANITIZE_MAGIC_QUOTES
With magic quotes (finally) gone from PHP, it is also time to
purge all remnants. The behaviour of the filter_var()
function, which can be used to sanitize input, is controlled through
various constants, one of them being
FILTER_SANITIZE_MAGIC_QUOTES
.
var_dump(filter_var("'", FILTER_SANITIZE_MAGIC_QUOTES));
Luckily, the deprecation message already tells you what to do:
PHP Deprecated: filter_var():
FILTER_SANITIZE_MAGIC_QUOTES is deprecated,
use FILTER_SANITIZE_ADD_SLASHES instead in ...
The fix is really simple, use the newly added
FILTER_SANITIZE_ADD_SLASHES
instead:
var_dump(filter_var("'", FILTER_SANITIZE_ADD_SLASHES));
Remember: nobody ever said that escaping of data is bad by itself, on the contrary! The bad idea had been to make this happen magically, so essentially we are just talking about a rename of the filter here.
Deprecate
strip_tags
Filter for Streams, and
fgetss()
The built-in PHP function strip_tags()
removes HTML
tags, PHP tags, and NULL bytes from a given string. There also is a
stream filter that does the same, but operates on a stream of data
rather than a string in memory.
To try this filter out, we need to create a file
test.html
, containing some HTML code:
<p>This is <b>HTML</b> code</p>
Now, we create a PHP script to read this file and apply the
strip_tags
filter:
$handle = fopen(__DIR__ . '/test.html', 'r+');
stream_filter_append($handle, "string.strip_tags", STREAM_FILTER_READ);
var_dump(stream_get_contents($handle));
This will output:
PHP Deprecated:
stream_filter_append():
The string.strip_tags filter is deprecated in ...
string(18) "This is HTML code
"
As of PHP 7.3, the strip_tags
filter on streams has
been deprecated, because running this filter on a stream is
technically pretty complex and thus error-prone.
Note that the function strip_tags()
itself is not
affected, so if you need to strip tags, you can still read the whole
file and run strip_tags()
on the string in memory.
The built-in function fgetss()
internally does the
same thing: it reads from the current position of a stream,
stripping tags. fgetss()
has thus also been deprecated.
Using the same test.html
file from above, we could also
run:
$handle = fopen(__DIR__ . '/test.html', 'r+');
var_dump(fgetss($handle));
This achieves the same result, but also comes with a deprecation warning:
PHP Deprecated:
Function fgetss() is deprecated in ...
string(18) "This is HTML code
"
Last but not least, the fgetss()
method of PHP’s
standard library class SplFileObject
has also been
deprectated, as well as the function gzgetss()
which
allows you to directly read from a gzip-compressed file.
Deprecate Non-String Needles in Search Functions
With increasing type safety, more and more little weirdnesses in PHP surface, and are subsequently fixed. A good example are various functions that allow you to search a given string (“haystack”), looking for a substring (“needle”). Depending on which function is used, the result is either a boolean value (“haystack contains the needle”), or the position of a substring, the position of the first or last occurence, for instance.
Up to version 7.3, PHP allowed passing of a non-string value as the needle:
var_dump(strpos('haystack', 42));
This will now result in:
PHP Deprecated:
strpos(): Non-string needles will be interpreted as strings in the future.
Use an explicit chr() call to preserve the current behavior in ...
bool(false)
Like most of the new deprecation messages that PHP 7 emits, this
one also directly tells you what to do. All other string search
functions are affected as well, namely strpos
,
strrpos
, stripos
, strripos
,
strstr
, strchr
, strrchr
and
stristr
.