The PHP 7.4 series (Deprecations)

Coding (Php 7.x)

Nov 26, 2019

This article describes all the features that have been deprecated in PHP 7.4 and the alternative you must use when upgrading your web applications.
 
/img/blog/php-7-4-deprecations.jpg

Introduction

 

Once again PHP 7.4 is coming and it is time to book a few hours out of your week to review what are the new features, what has been deprecated and the overall changes on PHP core language.

 

In the previous episode of this series, we have seen the new feature, the code that will accompany us in the following years of web development.

 

In this article we are going to focus on ALL the deprecation of PHP 7.4:

 

What are deprecations?

 

In programming deprecation is the deterrent of using part of the code, they can be keywords, functions or practices because their use is no longer effective or safe.

Likely, a deprecated feature will probably be deleted in the future.

 

It is extremely important to remove and refactor the parts of your code that are signalled as deprecated, 

 

Think for a second if a website that still uses hashing algorithms 5 or 10 years old, I would prefer avoiding to put my credit card’s details on it, I am sure you do too.

 

This series

 

This article is part of the series called “PHP 7.4” and includes:

 

  1. New features of the language
  2. Deprecation
  3. PHP 7.4 (Changes & Performance)
     

 

 

Table of content

 

 

 

 

 

 

Let’s get to the nitty-gritty, what has been deprecated?

 

PHP’s precedences will change level for the concatenation Operator 

 

A lot to explain here so let’s start with the basics,

 

In elementary school you learned that 2 + 4 * 6 = 26,

 

The reason is that in your mind you did the following steps:

  1. 2 + 4 * 6
  2. 2 + (4 * 6)
  3. 2 + 24
  4. 26

 

This rule is called precedence and you know that multiplication and division have precedence over sum and subtraction.

 

Now you are a grown-up man (or woman) and you are coding with PHP.

 

The same rule applies, but… they are just not the same and way more complicated.

 

We can now add the concept of associativity using another example,

 

6 - 4 - 2 = 0

 

The reason is that subtraction is associate at the left (or left-associative), so you do 6 - 4 = 2 then 2 - 2 resulting in 0;

 

To better understand this watch the equal or any other assignment symbols, they all are right-associative which measn that $a = $b = $c is grouped as $a = ($b = $c).

 

Are you still with me?

 

Good, let’s step up a level,

 

How about non-associative operators?

 

The ‘new’, ‘instanceof’, ‘<’, ‘>’, ‘!=’, ‘===’, etc are all PHP non-associative operators.

 

Operators that have equal precedence and are non-associative cannot be used next to each other.

 

Open your IDE and run “2 < 4 > 2” to test yourself.

 

A piece of advice from the Official PHP manual is to use parentheses, even if it doesn't need to, it definitely helps the readability of your script.

 

A problem that the PHP core team has solved (partially) is that the concatenation operator has the same precedence of the sum and subtraction operator.

 

This means that if you do this in PHP 7.3:

 

echo "the sum of 2 and 4 is: " . 2 + 4;

 

You will see this error showing up on your screen: “Warning: A non-numeric value encountered” 

 

The reason is that PHP does: echo ("the sum of 2 and 4 is: " . 2) + 4;

 

Remember, the symbols '+', '-' and '.' are all left-associative operators and they all have the same precedence.

 

In the next versions this is going to be solved:

 

In PHP 7.4 the language will emit a deprecation notice that tells you to use parentheses when needed.

 

In PHP 8 the precedence of these operators will change and the concatenation will be a level below.

 

 

If the concept above sees difficult have a look at the article PHP basics

 

Below you will find a list of operators in order of precedence, the highest-precedence ones are at the top, operators that are on the same line have an equal level or precedence:

 

  1. the operators clone new are non-associative;
  2. the operator ** is right-associative;
  3. the operators ++ -- ~ (int) (float) (string) (array) (object) (bool) @ are right-associative;
  4. the operator instanceof is non-associative;
  5. the operator ! is right-associative;
  6. the operators * / % are left-associative;
  7. the operators + - . are left-associative;
  8. the operators << >> are left-associative;
  9. the operators < <= > >= are non-associative;
  10. the operators == != === !== <> <=> are non-associative;
  11. the operator & is left-associative;
  12. the operator ^ is left-associative; 
  13. the operator | is left-associative; 
  14. the operator && is left-associative; 
  15. the operator || is left-associative; 
  16. the operator ?? is right-associative; 
  17. the operator ? : is left-associative; 
  18. the operators = += -= *= **= /= .= %= &= |= ^= <<= >>= are right-associative;
  19. the operator yield from is right-associative;
  20. the operator yield is right-associative;
  21. the operator and is left-associative; 
  22. the operator xor is left-associative; 
  23. the operator or is left-associative;

 

 

Deprecation of the left-association to chaining ternary operators 

 

Little secret, 

 

There is a ‘bug’ in the ternary operator of PHP!

 

 

The code in the following example ...

 

$OliverAge = 2:

$result = $OliverAge == 2 ? 'is two' : $OliverAge==4 ? 'is four' : $OliverAge==6 ? 'is six' : 'is not!';

 

... is always going to evaluate the false conditions.

 

It is just how the PHP parser works.

 

Unlike other programming languages, in fact, as you can see from the list in the previous section the '?' symbol in PHP is left-associative.

 

This is not a common behaviour and to solve the problem and not let down web developers coming from other languages Nikita Popof successfully proposed (the proposal has been approved with 35 votes to 10) to update this feature with a two-step process:

 

In PHP 7.4, this type of ternaries operators without explicit parentheses will throw a deprecation warning.

 

In PHP 8.0 instead, there will be a proper compile runtime error.

 

If you want to use chaining ternary operator without encounter errors what you need to do is to circumscribe each operation within parenthesis like so

 

$OliverAge = 2:

$result = ($OliverAge == 2 ? 'is two' : $OliverAge==4) ? 'is four' : 'is not!';

 

In here we are defining the precedence, thus this snippet is going to work just fine;

 

 

Exceptions allowed in __toString 

 

This feature has been discussed for ages, literally before PHP 5.1.

 

Johannes Schlüter, currently a member of Oracle's MySQL engineering team, was the release manager of PHP 5.3 and regarding the impossibility to throw exceptions within __toString() magic method said this:

 

“...there is no way to ensure that an exception thrown during a cast to a string would be handled correctly by the Zend Engine, and this won't change unless large parts of the Engine are rewritten...”

 

As you can see that was a big issue,

 

Let’s step back for a second and start from the beginning:

 

__toString() is a magic method provided by PHP

 

It allows us to decide how to treat a class when it is managed as a string, for example in case we echo an object.

 

Throwing an exception inside __toString() before PHP 7.4 was forbidden and if you try to do so the code will throw a fatal error.

 

The reason behind that is that string conversions are performed in many places throughout the engine and standard library, and not all of these places are ready to deal with exceptions.

 

The current workaround regarding this problem is to use an error handler as Symfony does:

 

set_error_handler(function() {
  throw new Exception();
});

try {
  (string) new stdClass;
} catch (Exception $e) {
  echo "(string) threw an exception...\n";
}

 

This technique relies on the $errcontext parameter, which, from PHP 8 onwards, won’t be available anymore.

 

What Nikita Popov has proposed is to allow this method to throw errors, and convert the “could not be converted to string” and “__toString() must return a string value” fatal errors into proper Error exceptions.

 

 

Curly brackets for array and string access

 

Before PHP 7.4 accessing an array’s value could be done in two different ways:

 

Using square brackets and using curly brackets.

 

Even though both methods were working the latter was way less common and according to Andrey Gromov could cause confusion in readability.

 

A good point that he made in his proposal was that the curly brace syntax is almost completely undocumented and it has less functionality compared to the normal bracket syntax. 

 

An example is that curly brackets cannot be used to create an array, for pushing an element into an array neither for list assignment.

 

In all three cases, it will result in a Parse error: syntax error.

 

Gromov’s proposal consists in deprecate curly brace syntax altogether and does not make accessing array elements and string offsets possible anymore.

 

 

This is not the first time PHP developers talk about this, in fact, this feature was deprecated in PHP 5.1 but reinserted before the official release.

This proposal instead will be definitely releases having been voted with 37 to 6 votes.

 

// Until PHP 7.3
$array = [1, 2];
echo $array[1]; // prints 2
echo $array{1}; // also prints 2

// Creating an array 
$array = [1, 2]; // works
$array = {1, 2}; // Parse error: syntax error, unexpected '{'

// Pushing an element inside an array
$array[] = 3;
echo $array[2]; // prints 3
$array{} = 3; // Parse error: syntax error, unexpected '}'

 

 

Short Open Tags

 

During the two decades of PHP, there have been several open and close tags allowed.

 

This trait of the language has been discussed and refactored during the release of PHP 7.0.

 

PHP short open tag is still available though and it has created several problems when dealing with good practices.

 

There are several reasons why you should avoid it, 

 

PHP's short open tags conflict with the XML tag

 

Also since open tags are conditioned by the INI file the source code may give problems if PHP that relies on the short open tags is executed on a configuration where it is not enabled.

 

This like several other deprecations we have seen today is a two-step process, a deprecation notice will be thrown in PHP 7.4 and the complete removal will happen in PHP 8.0.

 

Be careful before upgrading your script,

 

This feature is not a backward compatible

 

All the old open tag in your application must be converted to the standard open tag

 

The good news is that this procedure can be automatically completed by using the “full_opening_tag” fixer from PHP-CS-Fixer 

 

 

The real type deprecated

 

One of the big goals of PHP 7.4 is to simplify the code in preparation of PHP 8.0.

 

One way to do that is to eliminate all the features that are not commonly used.

 

One of these features is the float type.

 

The float type in PHP has two aliases, double and real.

 

Although double is rarely used we cannot even say the same for the real type.

 

The proposal to deprecate the real cast and the is_real() function has passed with 35 to 7 votes.

 

What you need to do when upgrading your code is to be sure that all your ‘real’ variable and is_real() function are going to be changed in float and is_float().

 

 

Magic quotes legacy

 

I believe that the majority of the readers of this post haven’t ever seen magic quotes and probably do not know what they are so let’s start with a bit of history lesson,

 

A long-time ago, If you were a beginner in PHP and you were to write a SQL query you could use this process to escape data that was arriving from user input into a PHP script.

 

The goal was to overcome SQL injection, but rather than be a security feature magic quotes were a feature developed for convenience.

 

They existed to help beginner write queries without the necessity to learn about escaping or accurately quoting the incoming data.

 

Problem is that they didn't stop malicious attacks to databases.

 

For this reason, this feature has been criticised for a long time.

 

It has actually been deprecated and then deleted in old versions of PHP (respectively PHP 5.3 and 5.4).

 

Now as I said this is not a feature anymore since the 1st March 2012 but it is still carrying on some weight on the core PHP,

 

This ballast are the get_magic_quotes_gpc() and get_magic_quotes_runtime() methods are going to be deprecated in PHP 7.4.

 

Both of them were used to verify the setting in a PHP script and returned a boolean.

 

The function get_magic_quotes_gpc() used to gets the configuration setting of magic_quotes_gpc (Get/Post/Cookie operations) whereas the get_magic_quotes_runtime() gets the active configuration setting of magic_quotes_runtime.

 

What you need to do before upgrading your PHP is to remove these function from your script.

 

This proposal passed with a result of 46 votes to 0.

 

array_key_exists() with objects

 

We need 3 steps to explain this proposal:

  1. Describe what the function array_key_exists() does;
  2. Describe whey this function worked with object
  3. Describe why this feature has to be deleted

 

Let’s start with number one: 

 

Put simply, the array_key_exists() function verify a specific key within an array.

 

If you as a developer are using it inside your script you are expecting a true or false as an answer depending on if the key used as parameter exists or not.

 

Now, for backward compatibility reasons, this function returned a boolean even if the variable that needed to be checked was an object defined as an array.

 

The result here has never been reliable and you must be sure that what you are using is an actual array

 

use property_exists() on object instead

 

The proposal was to throw a deprecation warning if an object is passed to array_key_exists() and it passed with contrary votes.

 

 

 

FILTER_SANITIZE_MAGIC_QUOTES

 

Another piece of code related to magic quotes.

 

As we have seen they have been deprecated and removed in PHP 7.4.

 

filter_var() has a filter extension named FILTER_SANITIZE_MAGIC_QUOTES, it sanitizes a variable by simulating the call of another PHP function the addslashes() in this case.

 

This post is all about sanitization:

 

Since we won’t have magic quotes anymore make sense to move on definitely and substitute FILTER_SANITIZE_MAGIC_QUOTES with FILTER_SANITIZE_ADD_SLASHES.

 

 

The proposal here was to Emit a deprecation notice when that filter was called and advise web developer to use FILTER_SANITIZE_ADD_SLASHES instead.

 

$var="Oliver's here!";
var_dump(filter_var($var, FILTER_SANITIZE_ADD_SLASHES));

string(14) "Oliver\'s here!"

 

 

Reflection export() methods

 

A reflection is an amazing tool in PHP,

 

If you do not know what they are please have a look at this post by Philip Brown. 

 

They help you in a lot of ways, one of the interfaces of the Reflection API is the Reflector interface.

 

It is an interface implemented by all exportable Reflection classes and it has two methods.

 

A __toString() method and a static export() one.

 

The export method is a weird one because even though does not accept any parameter, it is implemented with varying signatures in each subclass,

 

Depending on the parameter it can behave as a class construction and a __toString() method.


 

ReflectionFunction::export('Brad');
// same as
echo new ReflectionFunction('Brad'), "\n";

$string = ReflectionFunction::export('Brad', true);
// same as
$string = (string) new ReflectionFunction('Brad');

 

 

As you can see from the snippet above the functionality of this method can be easily replicated and actually will make more sense to use the alternative way rather than using the export method.

 

The proposal, that passed with 37 votes to 4, consisted of removing this method from the Reflector interface and deprecate its implementations.

 

In PHP 8 it will be permanently removed.

 

 

mb_strrpos() won’t take the encoding parameter as third anymore

 

Here is another deprecation that is going to make PHP cleaner and hopefully faster.

 

The functions strrpos() and mb_strrpos() are string PHP function.

 

They accept several parameters and find the position of the last occurrence of a substring in a string injected a parameter.

 

Here is an example of the basic function:

 

The first parameter is the string you want to search into, then the actual value you are looking for, as a third optional parameter we have the offset.

 

strrpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) : int

var_dump(strrpos("This article is about PHP 7.4","PHP"));
int(14)

 

On the other side mb_strrpos() is a bit different, 

 

It is a multibyte string function and a few more parameters.

 

mb_strrpos ( string $haystack , string $needle [, int $offset = 0 [, string $encoding = mb_internal_encoding() ]] ) : int

 

The problem that this proposal is trying to solve is that, in PHP 5.2, the encoding parameter was moved to the fourth position from the third that it held, and for backward compatibility is still worked,

 

In PHP 7.4 this is going to throw a deprecation warning. 

 

In PHP 8 the third argument will only accept an integer type that will be considered the offset.

 

 

 

implode() parameter order mix

 

The couples of PHP functions implode() and explode() have been some of my favourites and used string functions since I started my web development journey.

 

And they have been in PHP forever.

 

The implode function takes a string (called glue) and an array of elements (pieces) and create a string using the glue as a divider in between all the pieces.

 

You can also use the implode() function without any glue.

 

The parameters of the two functions have the same order, the glue and the array of pieces for the implode and a string to define the delimiter and the actual sentence that need to become an array for the explode function.

 

For compatibility reasons, the implode() function accepted parameters in either order. 

 

The PHP 7.4 proposal order to emit a deprecation warning in the case the glue is used as a second parameter.

 

This will keep the parameter order consistent between the two related functions.

 

Invoking the function only using the array continues to be allowed and does not generate any error.

 

For consistency with explode(), however, it may be less confusing to use the documented order of arguments.

 

 

Unbinding $this from non-static closures

 

The concept of closures is not really new but is surely uncommon, 

 

Unlike other languages for instance JavaScript where closures can be defined as a scope.

 

In PHP, a closure class is a callable anonymous class, to which we can bound our parameters.

 

Closure classes are used to represent anonymous functions.

 

A closure class has several methods allowing it to control anonymous function after they have been created.


 

closure {

    private __construct ()

    public static bind ( Closure $closure , object $newthis)

    public bindTo ( object $newthis )

    public call ( object $newthis)

    public static fromCallable ( callable $callable )

    public __invoke()

}

 

Anonymous functions, yield objects of ‘this’ type, but, before PHP 7.4, web developers could unbind the $this variable from closure by using the method:

$closure->bindTo(null).

 

From PHP 8 $this is always going to exist inside non-static method, the proposal suggest that it is sound to have a similar behaviour inside closure classes.

 

The proposal consisted in deprecate unbinding $this from a non-static closure declared inside non-static methods, 

 

 

Deprecate the hebrevc() function

 

The function hebrev() and hebrevc() are used to convert Hebrew logical text to Hebrew visual text.

 

The Visual text is applicable when there is not support of Unicode bidi  like in some terminal.

 

This application should never be used in HTML pages, so the proposal aims to deprecate the function.

 

In case your script need to convert Hebrew text into visual text it is suggested to inserts HTML line breaks before all newlines in the string are converted to visual text

 

You can do it using the following snippet:

 

nl2br(hebrev($hebrewText))

 

 

Deprecate the convert_cyr_string() function

 

Another legacy function that converts a string of text in a different character.

 

convert_cyr_string() allowed the conversion between Cyrillic character sets.

 

This is coming from PHP 4 when there weren’t better solutions.

 

Now you can do it and get better performances by using mb_convert_encoding(), iconv()

 

The first is taking the string to be converted as a first argument and the type of encoding as the latter.

 

The second function having the input charset as a first argument, the output charset as a second and the text to be converted as third.


 

/* Convert internal character encoding to SJIS */
$greet = “hello”;
$greet = mb_convert_encoding($greet, "SJIS");

$text = "This is the Euro symbol '€'.";
echo 'TRANSLIT : ', iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text), 
TRANSLIT : This is the Euro symbol 'EUR'.

 

This proposal passed with 25 votes to 7.

 

 

Deprecate the money_format() function

 

If you needed to format money of a specific currency the PHP function money_format() was the way to go, but it has two main problems:

 

  1. This function uses locale-specific settings;
  2. It is not supported on all platforms;

 

At the moment of this writing intl (or Internationalization extension) provide a similar feature that avoids these cited issues.

 

In specific the function to use is NumberFormatter::formatCurrency()

 

It accepts a float variable as value and a string indicating the currency.

 

$fmt = new NumberFormatter( 'de_DE', NumberFormatter::CURRENCY );
echo $fmt->formatCurrency(1234567.891234567890000, "EUR");
echo $fmt->formatCurrency(1234567.891234567890000, "RUR");

1.234.567,89 €
1.234.567,89 RUR

 

intl also supply NumberFormatter::parseCurrency() that parse a currency number

 

  

 

 

Deprecate the ezmlm_hash() function()

 

Another legacy function inherited from PHP 4.0.2.

 

It calculated the hash value needed by EZMLM, a system that has not been maintained and was last released more than a decade ago.

 

 

Deprecate the restore_include_path() function

 

The function restore_include_path() is used to restores the include_path configuration to its original master value as set in php.ini.

It is the alias of ini_restore('include_path')

 

You cannot user set_include_path() and restore_include_path() as a pair, plus this is not safe.

 

The proposal aims to remove this function since it does not provide any convenience over ini_restore('include_path').

 

 

Here is how you use ini_restore():

 

$setting = 'y2k_compliance';
echo 'Current value for \'' . $setting . '\': ' . ini_get($setting), PHP_EOL;


ini_set($setting, ini_get($setting) ? 0 : 1);
echo 'New value for \'' . $setting . '\': ' . ini_get($setting), PHP_EOL;

ini_restore($setting);
echo 'Original value for \'' . $setting . '\': ' . ini_get($setting), PHP_EOL;

Current value for 'y2k_compliance': 1
New value for 'y2k_compliance': 0
Original value for 'y2k_compliance': 1

 

 

Deprecate the allow_url_include() function

 

Ini directives allow you to be in control of various facey of your web applications 

 

allow_url_include is one of this directive and it permits, alongside allow_url_fopen(), to use require, require_once, include and include_once constructs to use URL stream wrappers. 

 

Allowing this functionality in your application is quite dangerous security-wise

it is because the path passed to one of the include commands can contain external data, and it may be difficult to spot.

 

This proposal consists of adding a deprecation notice when allow_url_include is set to 1 on startup.

 

 

Conclusion

 

This post was huge but necessary to understand where PHP is going and how these updates will further change PHP 8 and your daily basis work.

 

My impression is that PHP is getting lightweight, simplifying its syntax and getting rid of all the superfluous functions still available in the core language.

 

It is also modernizing by use more strict typed variables and fixing issues with precedences and associations.

 

Where you can go from here?

 

In the next chapter you will see other changes and the performance of PHP 7.4 and PHP 8, or, if you haven't already, you can read the first episodes of this series about all the features of PHP 7.4.

 

 
 
If you like this content and you are hungry for some more join the Facebook's community in which we share info and news just like this one!

Other posts that might interest you

Coding (Php 7.x) Nov 18, 2019

The PHP 7.4 guide (new features)

See details
Coding (Php 7.x) Dec 2, 2019

PHP 7.4 (Changes & Performance)

See details
Coding (Php 7.x) Dec 5, 2019

Design Patterns in PHP [Factory Method Pattern]

See details
Get my free books' review to improve your skill now!
I don't want to improve