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:

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.