text: New language features in PHP 7
  In this article, we present new language features of PHP 7. The article focuses on the features of the core language. For our examples, we use PHP CLI. PHP tutorial is a concise tutorial of PHP language on ZetCode. In the PHP filesystem functions article, we cover numerous PHP functions related to filesystem.
  Between years 2014 and 2015, a new major PHP version was developed, which was numbered PHP 7. After some debate among developers, version 6 was skipped in order to avoid confusion with PHP Unicode experiment, which was referred to as PHP 6 in the press. First, we are going to show how to install PHP 7 from the sources.
  Installing PHP
  We download PHP from the
  page. We have downloaded
  php-7.0.4.tar.bz2 file.
  $ bunzip2 php-7.0.4.tar.bz2 $ tar -xf php-7.0.4.tar $ cd php-7.0.4/
  We decompress the file and move into the build directory.
  $ sudo apt-get install libreadline-dev $ sudo apt-get install libicu-dev
  We need to install readline development library for PHP interactive shell and the development files for international components for Unicode.
  $ ./configure --with-readline --enable-intl
  We run the
  configure script with readline and internationalization
  support enabled.
  $ make $ sudo make install
  We build and install PHP. It is possible that we need to install some additional
  packages. For instance, the author had to install
  libxml2-dev library.
  $ sudo cp php.ini-development /usr/local/lib/php.ini $ sudo ln -s /usr/local/lib/php.ini /etc
  We copy the
  php.ini file and make a link to it in the
  /etc
  directory.
  $ php -a Interactive shell php > echo PHP_VERSION; 7.0.4
  We run PHP in interactive mode and get the version of PHP.
  Integer division
  The division operator (/) returns a float point value. The
  divint() function performs integer division.
  The first parameter is the dividend, the second parameter
  is the divisor.
  <?php echo 7/3, "\n"; echo intdiv(7, 3), "\n"; ?>
  The example prints values of a floating point and integer divisions.
  $ php integer_division.php 2.3333333333333 2
  This is the output of the
  integer_division.php program.
  The spaceship operator
  The spaceship operator (<=>), also known as combined comparison operator,
  can be used to make chained comparisons more concise. In behaviour, it is similar to
  to
  strcmp() or
  version_compare().
  $a <=> $b
  This expression evaluates to -1 if
  $a is smaller than
  $b,
  0 if
  $a equals
  $b, and 1 if
  $a is greater than
  $b.
  ($a < $b) ? -1 : (($a > $b) ? 1 : 0)
  The expression is rewritten without the spaceship operator.
  <?php echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 echo "\n"; echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 echo "\n"; echo [] <=> []; // 0 echo [1, 2, 3] <=> [1, 2, 3]; // 0 echo [1, 2, 3] <=> []; // 1 echo [1, 2, 3] <=> [1, 2, 1]; // 1 echo [1, 2, 3] <=> [1, 2, 4]; // -1 echo "\n"; ?>
  The example uses the spaceship operator on numbers, strings, and arrays.
  echo 1 <=> 1; // 0
  Numbers are compared by their size.
  echo "a" <=> "b"; // -1
  Strings are compared lexically; e.i. by their alphabetical order.
  echo [1, 2, 3] <=> [1, 2, 1]; // 1
  In case of arrays, corresponding array elements are compared with one another.
  $ php spaceship_operator.php 0-11 0-11 0011-1
  This is the output of the
  spaceship_operator.php program.
  The null coalescing operator
  The null coalescing operator (??) is a syntactic sugar for the common
  case of having to use a ternary operator in conjunction with
  isset(). It returns
  its first operand if it exists and is not
  NULL; otherwise it returns its
  second operand.
  php > $mycolour = $colour ?? "blue"; php > echo $mycolour; blue
  Since the
  $colour variable is not defined, the
  ?? operator
  returns its second operand.
  php > $mycolour = isset($colour) ? $colour : "blue"; php > echo $mycolour; blue
  In previous versions of PHP, we would need to used the
  isset() function.
  Scalar type declarations
  Scalar type declarations are type hints for function parameters. There are two types
  of declarations: coercive (default) and strict. The following types for parameters can
  now be enforced
  string,
  int,
  float,
  and
  bool.
  The types are enforced with the
  declare() function.
  <?php // declare(strict_types=1); function add(int $a, int $b) { return $a + $b; } $r = add(4, 6); echo "$r\n"; $r = add("4", "6"); echo "$r\n"; ?>
  In the coercive mode, the example prints 10 for both cases. If we enable
  the strict mode by removing the comment, we receive the following error
  Fatal error: Uncaught TypeError: Argument 1 passed to add()
  must be of the type integer, string given.
  Return type declarations
  The return type declarations specify the type of the value that is returned from a function. The same types are available for return type declarations as are available for argument type declarations.
  <?php declare(strict_types=1); function add( $a, $b) : int { return $a + $b; } $r = add(4, 6.0); echo "$r\n"; ?>
  The function has an
  int return type declared. We pass
  a floating point value to the function which results in a float return
  value. The program ends with this error:
  Fatal error: Uncaught TypeError:
  Return value of add() must be of the type integer, float returned.
  Unicode codepoint escape syntax
  The syntax takes a codepoint in hexadecimal form and outputs that codepoint in UTF-8 to a double-quoted string or a heredoc. Any valid codepoint is accepted, with leading 0's being optional. (Code points are numerical values that represent a character.)
  <?php echo "\u{13C7}", "\n"; echo "\u{1307}", "\n"; ?>
  The example prints a Cherokee letter que and ethiopic syllable jwa.
  $ php unicode_codepoints.php Ꮗ ጇ
  This is the output of the
  unicode_codepoints.php program.
  IntlChar class
  The new
  IntlChar class provides access to a number of utility
  methods that can be used to access information about Unicode characters.
  <?php echo IntlChar::charName('Ꮗ'), "\n"; echo IntlChar::charName('ጇ'), "\n"; ?>
  The example uses the
  IntlChar::charName() function to
  retrieve the name of two Unicode characters.
  $ php intlcharex.php CHEROKEE LETTER QUE ETHIOPIC SYLLABLE JWA
  This is the output of the
  intlcharex.php script.
  Anonymous classes
  Anonymous classes are classes that do not have a name. They are useful when simple, one-off objects need to be created.
  <?php $c = new class { public function say() { echo "This is an anonymous class\n"; } }; $c->say(); ?>
  We assign an object to the
  $c variable; the object
  is created from a class that does not have a name.
  $ php anonymous_class.php This is an anonymous class
  This is the output of the
  anonymous_class.php script.
  Expectations
  Expectations are backwards compatible enhancement to the older
  assert()
  function. It is possible to have zero-cost assertions in production code and
  to provide the ability to throw custom exceptions when the assertion fails.
  The
  zend.assertions configuration setting can have one of three values:
  - 1 — generate and execute code (development mode)
  - 0 — generate code and jump around at it at runtime
  - -1 — don't generate any code (zero-cost, production mode)
  The
  assert.exception sets whether an exception is thrown when an
  assertion fails. This is switched off by default to remain compatible with the
  old
  assert() function.
  <?php abstract class Grades { const A = 0; const B = 1; const C = 2; const D = 3; const E = 4; const FX = 5; } const G = 6; //$grade = Grades::A; $grade = G; switch ($grade) { case Grades::A: echo "Outstanding\n"; break; case Grades::B: echo "Superior\n"; break; case Grades::C: echo "Good\n"; break; case Grades::D: echo "Satisfactory\n"; break; case Grades::E: echo "Low pass\n"; break; case Grades::FX: echo "Failure\n"; break; default: assert (false, "Unrecognized grade passed through switch: {$grade}"); } echo "code continues\n"; ?>
  We have a system of college grades.
  //$grade = Grades::A; $grade = G;
  A wrong value is given to the
  $grade variable.
  default: assert (false, "Unrecognized grade passed through switch: {$grade}");
  We place an assertion at a location we assume will not be reached.
  $ php expectations.php Warning: assert(): Unrecognized grade passed through switch: 6 failed in /home/janbodnar/prog/php7/expectations.php on line 44 code continues
  The script contains the above warning, but it continues.
  ini_set('assert.exception', 1);
  It is possible to enable exceptions by setting the
  assert.exception
  configuration. This time the script fails with
  Fatal error: Uncaught AssertionError:
  Unrecognized suit passed through switch: 6.
  The levels paramter of dirname()
  The
  dirname() function returns the parent's directory path.
  The new
  levels parameter tells how many parent directories
  to go up.
  <?php echo dirname('/usr/local/bin').PHP_EOL; echo dirname('/usr/local/bin', 1).PHP_EOL; echo dirname('/usr/local/bin', 2).PHP_EOL; echo dirname('/usr/local/bin', 3).PHP_EOL; ?>
  In the script, we utilize the new optional parameter of
  the
  dirname() function.
  $ php dirlevels.php /usr/local /usr/local /usr /
  This is the output of the
  dirlevels.php script.
  Array constants in define()
  Since PHP 5.6 it is possible to define constant arrays with the
  const keyword.
  In PHP 7, a constant array can be created with
  define() too.
  <?php const POSSIBLE_GRADES = ['A', 'B', 'C', 'D', 'E', 'FX']; define('ALLOWED_IMAGE_EXTENSIONS', ['jpg', 'jpeg', 'gif', 'png']); print_r(POSSIBLE_GRADES); print_r(ALLOWED_IMAGE_EXTENSIONS); ?>
  The code example creates two array constants; one with the
  const keyword
  and one with the
  define() function.
  $ php array_constants.php Array ( [0] => A [1] => B [2] => C [3] => D [4] => E [5] => FX ) Array ( [0] => jpg [1] => jpeg [2] => gif [3] => png )
  This is the output of the
  array_constants.php script.
  New use syntax
  The
  use keyword allows to group multiple declarations in
  one statement.
  <?php namespace ZetCode; class Night { function say() { echo "This is Night class\n"; } } class Day { function say() { echo "This is Day class\n"; } } function f1() { echo "This is f1()\n"; } function f2() { echo "This is f2()\n"; } ?>
  In the
  myfile.php we have two classes and two functions defined
  in a
  ZetCode namespace.
  <?php include 'myfile.php'; use ZetCode\{Day, Night}; use function ZetCode\{f1, f2}; $d = new Day(); $d->say(); $n = new Night(); $n->say(); f1(); f2(); ?>
  In the
  usegroup.php we use the classes and functions from
  ZetCode namespace.
  use ZetCode\{Day, Night}; use function ZetCode\{f1, f2};
  The new syntax of
  use allows to import several declarations
  in one statement.
  use ZetCode\Day; use ZetCode\Night; use function ZetCode\f1; use function ZetCode\f2;
  This is the syntax for previous versions of PHP.
  $ php usegroup.php This is Day class This is Night class This is f1() This is f2()
  This is the output.
  Closure call() method
  PHP 5.4 added the ability to bind closures to an object's scope.
  This process is simplyfied in PHP 7 with the
  call() method.
  <?php class Greeting { private $word = "Hello"; } $f = function($whom) { echo "$this->word $whom\n"; }; $obj = new Greeting(); $f->call($obj, 'Tom'); $f->call($obj, 'Jane'); ?>
  With a closure, we access a private variable of a class.
  $ php closure_call.php Hello Tom Hello Jane
  This is the output of the
  closure_call.php script.
  Generator return expressions
  A
  return statement can be used within a generator to enable
  for a final expression to be returned. This value can be retrieved with
  the
  getReturn() method, which may only be used once the generator
  has finishing yielding values.
  <?php srand(); function random_numbers($k) { for ($i=0; $i<$k; $i++) { $r = rand(1, 10); yield $r; } return -1; } $rns = random_numbers(10); foreach ($rns as $r) { echo "$r\n"; } echo $rns->getReturn() . PHP_EOL; ?>
  Our generator returns random values. At the end of the iteration, the generator returns -1.
  $ php generator_return.php 7 5 6 7 1 1 9 6 5 8 -1
  This is a sample output of the
  generator_return.php script.
  Generator delegation via yield from
  Generator delegation allows to yield values from another generator,
  Traversable object, or array by using the
  yield from
  keyword. Generator delegation promotes cleaner code and reusability.
  <?php function f1() { yield from f2(); yield "f1() 1"; yield "f1() 2"; yield from [3, 4]; yield "f1() 3"; yield "f1() end"; } function f2() { yield "f2() 1"; yield "f2() 2"; yield "f2() 3"; yield "f2() end"; } $f = f1(); foreach ($f as $val) { echo "$val\n"; } ?>
  In the example, we yield values another generator and an array.
  function f1() { yield from f2(); ...
  Values are yield from
  f2() generator.
  yield from [3, 4];
  It is also possible to yield values from an array.
  $ php generator_delegation.php f2() 1 f2() 2 f2() 3 f2() end f1() 1 f1() 2 3 4 f1() 3 f1() end
  This is the output of the
  generator_delegation.php script.
  Uniform variable syntax
  New uniform variable syntax allows combinations of operators that were previously disallowed; old operations can be achieved in terser code. The new syntax always follows a left-to-right evaluation order. The uniform variable syntax breaks backward compatibility in some expressions where old evaluation is used.
  <?php function e() { echo "This is e() \n"; }; function f() { echo "This is f() \n"; return e; }; function g() { echo "This is g()\n"; return f; }; g(); echo "***********\n"; g()(); echo "***********\n"; g()()(); ?>
  The example uses
  g()() and
  g()()(), which were not
  possible in earlier PHP versions.
  g();
  Here the
  g() function is executed.
  g()();
  This statement executes the
  g() function and the return
  of the
  g() function.
  g()()();
  The
  g() function is executed, the return of the
  g() function is executed, and the return of the return
  is executed.
  $ php uniform_variable_syntax.php This is g() *********** This is g() This is f() *********** This is g() This is f() This is e()
  This is the output of the
  uniform_variable_syntax.php script.
  The following is another example of a new syntax introduced with the uniform variable syntax.
  <?php class A { function f() { echo "f() of A\n"; } } class B { function g() { echo "g() of B\n"; return new A(); } } $b = new B(); $b->g()::f(); ?>
  The
  $b->g()::f() executes an
  f() method of a
  class
  A returned by method
  g().
  $ php uniform_variable_syntax2.php g() of B f() of A
  This is the output of the
  uniform_variable_syntax2.php script.
  In the third example, we have an immediately-invoked function expression, which is a term from the JavaScript language.
  <?php $v = (function() { return 11 - 5; })(); echo "$v\n"; ?>
  Immediately-invoked function expression is an anonymous function that is executed right after it is created.
  $ php uniform_variable_syntax3.php 6
  This is the output of the
  uniform_variable_syntax3.php script.
  Changes in exceptions and errors
  In PHP 7, an exception is thrown when a fatal and recoverable error (
  E_ERROR
  and
  E_RECOVERABLE_ERROR) occurs, rather than halting script execution. These
  fatal and recoverable errors are now instances of a new and separate exception class:
  Error. Some errors throw a more concrete error:
  TypeError,
  ParseError,
  ArithmeticError, and
  AssertionError.
  Other types of errors such as warnings and notices remain unchanged in PHP 7. Only fatal and recoverable errors throw exceptions.
  A new
  Throwable interface is introduced to unite the two exception branches:
  Exception and
  Error; they both implement the
  Throwable.
  <?php class A { public function say() { echo "This is class A\n"; } } try { $a = new A(); $a->say(); $a = null; $a->say(); } catch (Error $e) { echo "Error occured" . PHP_EOL; echo $e->getMessage() . PHP_EOL ; echo "File: " . $e->getFile() . PHP_EOL; echo "Line: " . $e->getLine(). PHP_EOL; } echo "Script continues\n"; ?>
  In the example, we call a method on
  null object.
  We catch the exception and handle it; the script then continues.
  $ php null_error.php This is class A Error occured Call to a member function say() on null File: /home/janbodnar/prog/php7/null_error.php Line: 17
  This is the output of the
  null_error.php script.
  DivisionByZeroError is an
  ArithmeticError which
  is thrown from
  intdiv() and the modulo (%) operator when the
  denominator is zero. The (\) division operator issues still
  a
  Warning: Division by zero warning.
  <?php $a = 4; $b = 0; try { $c = intdiv($a , $b); } catch (DivisionByZeroError $e) { echo "Error occured\n"; echo $e->getMessage() . PHP_EOL ; echo "File: " . $e->getFile() . PHP_EOL; echo "Line: " . $e->getLine(). PHP_EOL; } echo "$c \n"; echo "Script continues\n"; ?>
  In the example, we catch and report a
  DivisionByZeroError
  in a
  intdiv() function.
  $ php arithmetic_error.php Error occured Division by zero File: /home/janbodnar/prog/php7/arithmetic_error.php Line: 8 Script continues
  This is the output of the
  arithmetic_error.php script.
  Sources
  The following sources were used to create this article:
  In this article, we have presented new features of PHP 7 language. You may want to look at PHP tutorial now.