📜 ⬆️ ⬇️

What to expect when you expect a child: PHP 7, part 2

This is the second part of our miniseries of “What to expect from PHP7”. Read part 1

As you probably already know, PHP7 will come this year! And now is the time to find out what new he brings to us.

In the first part of this series, we looked at some of the most important changes in PHP7 and two major new features. In this article we will look at six more, which you definitely want to know about.

New unicode escape character


Adding a new escape character \u allows us to specify specific unicode characters inside PHP strings (yes, those emoji and not only) .
')
The syntax is - \u{CODEPOINT} , for example, green heart, , can be expressed as a php string: "\u{1F49A}" .

The union operator with a null value ( Null Coalesce Operator )


Another new operator - ?? . It returns the left operand if it is not NULL; otherwise, the right operand is returned.

Most importantly, it does not generate notice if the left operand is a nonexistent variable. Unlike the short ternary operator ?: It works like isset() .

You can also use chains of operators to return the first non-zero one from this set:

 $config = $config ?? $this->config ?? static::$defaultConfig; 

Binding closures during a call


With PHP5.4, Closure->bindTo() and Closure::bind() have come to us, which allow you to change the $this binding and call areas, together, or separately, creating a duplicate closure.

PHP7 now adds an easy way to do this right during a call, by binding $this and the call area with Closure->call() . This method takes an object as its first argument, and then any other arguments that will go to the closure:

 class HelloWorld { private $greeting = "Hello"; } $closure = function($whom) { echo $this->greeting . ' ' . $whom; } $obj = new HelloWorld(); $closure->call($obj, 'World'); // Hello World 

Grouping of declarations use


If you have ever had to import many classes from the same namespace, you were probably very happy when the IDE did all the basic work for you. For everyone else, and for brevity, PHP7 now has the ability to group the declaration of use statements . This will allow faster and more convenient to work with a large number of imports and make the code more readable:

 // Original use Framework\Component\SubComponent\ClassA; use Framework\Component\SubComponent\ClassB as ClassC; use Framework\Component\OtherComponent\ClassD; 

 // With Group Use use Framework\Component\{ SubComponent\ClassA, SubComponent\ClassB as ClassC, OtherComponent\ClassD }; 

Grouping can be used with constants and imported functions, you can mix everything together:

 use Framework\Component\{ SubComponent\ClassA, function OtherComponent\someFunction, const OtherComponent\SOME_CONSTANT }; 

Generator Improvement


return in generators

Two very interesting possibilities appeared in the generators. The first one is Generator Return Expressions , which allows to return the value after the (successful) completion of the generator.

Before PHP7, if you tried to return something in the generator, this led to an error. However, you can now call $generator->getReturn() to get the return value.

If the generator has not yet completed or threw an uncaught exception, the $generator->getReturn() call will generate an exception.

If the generator is complete, but not declared return , the method will return NULL .

Example:

 function gen() { yield "Hello"; yield " "; yield "World!"; return "Goodbye Moon!"; } $gen = gen(); foreach ($gen as $value) { echo $value; } // Outputs "Hello" on iteration 1, " " on iterator 2, and "World!" on iteration 3 echo $gen->getReturn(); // Goodbye Moon! 

Generator Delegation

The second feature is much more exciting: delegation of the generator . This allows you to return another iterative structure — whether it is an array, an iterator, or another generator.

It is important to understand that the iterations of the sub-structures are performed precisely through the outermost loop, as if it were a single flat structure, and not a recursive call.

This statement is also true when sending data to a generator or throwing exceptions. They are transmitted to the sub-structure, as if it were her immediate challenge.

The syntax is yield from <expression> . Let's look at an example:

 function hello() { yield "Hello"; yield " "; yield "World!"; yield from goodbye(); } function goodbye() { yield "Goodbye"; yield " "; yield "Moon!"; } $gen = hello(); foreach ($gen as $value) { echo $value; } 

At each iteration will be displayed:

  1. "Hello"
  2. ""
  3. "World!"
  4. "Goodbye"
  5. ""
  6. "Moon!"

It is worth mentioning another nuance: since the sub-structures introduce their own keys, it is quite possible that the same key will be returned in several iterations. Preventing this is your responsibility, of course, if it matters to you.

\EngineException


Handling fatal and catchable fatal errors in traditional PHP was impossible, or at least very complex. But with the addition of Engine exceptions , many of these errors will now throw an exception instead of the error itself.

Now, when a fatal or catchable fatal fatal error occurs, an exception will be thrown that allows you to handle the error correctly. If you do not touch it, it will lead to the traditional fatal error of an unhandled exception.

These exceptions are \EngineException objects, and unlike all user exceptions, they are not inherited from the base class \Exception . This is done specifically so that the existing code that catches the \Exception class does not catch fatal errors by changing its behavior. Thus, backward compatibility is maintained.

In the future, if you want to catch both traditional exceptions and engine exceptions, you will need to catch their new common parent class \BaseException .

In addition, parsing errors in the code executed by the eval() function will now throw a \ParseException , and a type mismatch will result in a \TypeException .

Example:

 try { nonExistentFunction(); } catch (\EngineException $e) { var_dump($e); } object(EngineException)#1 (7) { ["message":protected]=> string(32) "Call to undefined function nonExistantFunction()" ["string":"BaseException":private]=> string(0) "" ["code":protected]=> int(1) ["file":protected]=> string(17) "engine-exceptions.php" ["line":protected]=> int(1) ["trace":"BaseException":private]=> array(0) { } ["previous":"BaseException":private]=> NULL } 

Soon!


PHP 7.0.0 is only eight months old, and quite possibly it will be the fastest major release version in PHP history. While still in the alpha version, but now everything is going very well.

And you can help make it even better.

Check your code

Take the PHP7 vagrant box from Rasmus and run your tests or check your application on your checklist. Report bugs in the project, repeat regularly :)

Help GoPHP7-ext

One of the major obstacles to PHP7 is the large amount of work on updating all extensions for working with the new Zend Engine 3.

If you use an extension that is not very popular and well-known, and you don’t like its support level, or you have your own extensions - take a look at the GoPHP7-ext project and take part by transferring your extensions to a new engine.

Documentation

Each new PHP7 feature has its own RFC. All of them can be found on the PHP.net wiki and are a good starting point for writing new documentation. You can do this online in a GUI environment , including commit (if you have karma) or send a patch for review.

Conclusion


PHP 7 will be great !

Test your applications. Help migrate extensions.

PS Have you tried PHP7? How do you feel about innovations? Is there something you disagree with? When do you plan to upgrade to the new version? Write your thoughts on this in the comments.

Source: https://habr.com/ru/post/258139/


All Articles