PHP Syntax Changes 5.3.x - 7.0.x

June 8, 2016 by PHP  

Originally I was planning to do a little write-up about the latest syntax introduced into PHP 7.0.x, but then I noticed quite a significant number of syntax changes leading up to this version, many of which I was unaware of since I last used PHP in version 5.3.x.

So if you fell asleep (like me), here is a brief list of syntax changes (I could find) since PHP 5.3.x, I am not going to go into too much depth about these changes, think about this as a crash course.

Classes

  • Dynamic access to static methods (5.3.x)

    class LatLng {
       public static $lat = -25.7313;
       public static $lng = 28.2184;
    }
    
    $x = "LatLng";
    echo $x::$lat;

  • Late Static Binding (5.3.x)

    class SomeBaseClass {
        public static function Context() {
            echo __CLASS__;
        }
        public static function UsingLateBinding() {
            static::Context();
        }
    public static function UsingSelf() { self::Context(); } } class SomeDerivedClass extends SomeBaseClass { public static function Context() { echo __CLASS__; } } SomeDerivedClass::UsingLateBinding(); SomeDerivedClass::UsingSelf();
    This is all about scope, the self keyword resolves to the class in which it is being implemented ignoring context / inheritance, while a statically invoked function will take context / inheritance into account.

    E.g. in the example in the snippet above the Late Bound method will echo the name of the derived class calling it (SomeDerivedClass), while the method calling from the self keyword will echo the class it was originally implemented in (SomeBaseClass).

  • Traits (5.4.x)

    trait Logging 
    {
    	private function Write($message) { /* Do Something */ }
    }
    
    class SomeClass
    {
    	use Logging;
    	
    	public function __construct() {
    		$this->Write('Something');
    	}
    }
    
    class SomeOtherClass
    {
    	use Logging;
    	
    	public function __construct() {
    		$this->Write('Something');
    	}
    }

    Traits provides an alternative mechanism for code reuse to inheritance, in the preceding snippet you can see its basic usage, I will write an in-depth post in the near future (quite a subject on its own). I must however admit that I am currently of the opinion that traits must be avoided.

  • Class member access on instantiation (5.4.x)

    $a = (new SomeClass)->SomeMethod();

  • Class::{expr}() (5.4.x)

    class SomeClass
    {
    	public static function SomeMethod()
    	{
    		echo "Output";
    	}
    }
    
    SomeClass::{"SomeMethod"}();

  • Class name resolution via ::class (5.5.x)

    namespace CSTruter;
    class SomeClass { }
    
    echo SomeClass::class;

    The snippet above will output the name of the class along with its namespace.

  • Anonymous Classes (7.0.x)

    function SomeFunction($c)
    {
    	$c->SomeMethod();
    }
    
    SomeFunction(
    	new class {
    		public $Name = 'apple'; 
    		public function SomeMethod() {
    			echo $this->Name;
    		}
    	});


Namespaces (5.3.x)

One of the most important changes in PHP was the introduction of namespaces, thereby solving name collisions (ambiguity) issues and giving us the ability to alias names, improving readability and reusability of source code.

Combination Syntax

namespace CSTruter;
const SOMECONSTANT = 1;
class SomeClass {}
function SomeFunction() {}

namespace CSTruter\MVC;
const SOMECONSTANT = 2;
class SomeClass {}
function SomeFunction() {}


Bracketed Syntax

namespace CSTruter\MVC {
const SOMECONSTANT = 1;
class SomeClass {}
function SomeFunction() {}
}

namespace CSTruter {
const SOMECONSTANT = 2;
class SomeClass {}
function SomeFunction() {}
}

namespace { // Global Namespace
const SOMECONSTANT = 3;
class SomeClass {}
function SomeFunction() {}
}


Usage

echo SOMECONSTANT;
echo \CSTruter\SOMECONSTANT;
echo \CSTruter\MVC\SOMECONSTANT;

Importing / Aliasing (5.3.x)

use CSTruter\SomeClass;
use CSTruter\MVC\SomeClass as SomeOtherClass;

Alternatively

use CSTruter\SomeClass,
CSTruter\MVC\SomeClass as SomeOtherClass;


Or using Group use declarations (7.0.x)

use CSTruter\Example\{SomeClass,SomeOtherClass};

use function / use const (5.6.x)

use const CSTruter\MVC\SOMECONSTANT;
use function CSTruter\MVC\SomeFunction;


Constants

  • const keyword outside class definitions (5.3.x)

    const SOMECONSTANT = 1;
    class SomeClass {}

  • Constant Expressions (5.6.x)

    const SOMECONSTANT = E_ERROR | E_WARNING | E_PARSE;

  • Constant Array (5.6.x)

    const SOMECONSTANT = [1, 2, 3];


Operators

  • Short Ternary Operator (5.3.x)

    $x = null;
    $y = null;
    
    echo $x ?: $y ?: "Hello";

  • Right Associative Operator - Exponentiation (5.6.x)

    echo 2 ** 3;

  • Varargs / Rest Parameter (5.6.x)

    function SomeFunction($value, ... $values)
    {
    	print_r($values);
    	echo func_num_args(); // outputs 4, not cool
    }
    
    SomeFunction(1, 2, 3, 4);

  • Splat / Spread Operator (5.6.x)

    function SomeFunction($x, $y, $z) { echo $x + $y + $z; }

    $args = [1, 2, 3];
    SomeFunction(...$args);


  • Spaceship Operator (7.0.x)

    echo 1 <=> 1; // 0
    echo 2 <=> 1; // 1
    echo 1 <=> 2; // -1

    I must admit, it took me a while to figure out the necessity of this operator, but will talk about it in a future post.

  • Coalesce Operator (7.0.x)

    $a = null;
    $b = ["value" => 1];
    
    echo $a ?? $b["value1"] ?? $b["value"];
    echo $a ?: $b["value1"] ?: $b["value"]; // Undefined index: value1


Type Declarations

  • Scalar Type Declaration (7.0.x)

    function SomeMethod(int $key, string $value) { }

  • Return Type Declaration (7.0.x)

    function SomeMethod(float $value) : bool { }


Exceptions

  • Exception Nesting (5.3.x)

    function doSomething()
    {
    	try { 
    		throw new Exception("Something went wrong");
    	} 
    	catch(Exception $ex) { 
    		throw new Exception("Something else went wrong", 0, $ex); 
    	}
    }
    
    try { 
    	doSomething(); 
    } 
    catch(Exception $ex) {
    	print_r($ex);
    }

    Basically the whole inner exception thing (those familiar with C#).

  • Finally Keyword (5.5.x)

    try { 
    	throw new Exception('Something wrong');
    } 
    finally {
    	echo 'Still Do This';
    }
    echo 'Something to do';

    PHP finally added a finally block (see what I did there), code in the finally block will always be executed after the try/catch block, regardless of the thrown exception.

Dereferencing

  • Function array dereferencing has been added (5.4.x)

    function SomeMethod() {
    return ['Apple', 'Orange', 'Lemon'];
    }

    echo SomeMethod()[1];


  • Array literal dereferencing (5.5.x)

    echo ['The', 'Rain', 'In', 'Spain'][2];

  • String literal dereferencing

    echo 'The rain in spain'[2];

Other

  • Anonymous Functions aka closures (5.3.x)

    $a = function($value) {
    return $value;
    };

    echo $a('SomeValue');


  • goto operator (5.3.x)

    goto SomeSection;
    echo 'Unreachable Code';

    SomeSection:

    echo 'Something';


    goto

    I was rather surprised by the addition of the goto operator in PHP 5.3, I really thought we are better than this, hehehe.

  • Binary number format (5.4.x)

    echo 0b101;

  • Short Array Syntax (5.4.x)

    $fruit = ['Apples', 'Oranges', 'Bananas'];

  • yield Keyword (5.5.x)

    function SomeFunction()
    {
    	yield 'Apples';
    	yield 'Oranges';
    	yield 'Bananas';
    	echo '2';
    }
    
    echo '1';
    $generator = SomeFunction();
    echo '3';
    
    foreach($generator as $item) {
    	// Do Something
    }

    The yield keyword is at the heart of generators in PHP, which is basically an easier / more efficient way of implementing iterators.

    More efficient in that it allows us to iterate over data without needing to build an array in memory and like demonstrated in the snippet above (outputs 132), only generate data when needed.

  • yield from (PHP 7.0.x)

    function SomeFunction()
    {
    	yield 'Apples';
    	yield 'Oranges';
    	yield from SomeOtherFunction();
    	yield 'Bananas';
    	yield from ['Apricots', 'Grapes'];
    }
    
    function SomeOtherFunction()
    {
    	yield 'Pineapple';
    	yield 'Strawberries';
    }
    

    Yield from basically enables you to yield values from another generator, traversable object or array.

Additional Reading

Migrating from PHP 5.2.x to PHP 5.3.x
Migrating from PHP 5.3.x to PHP 5.4.x
Migrating from PHP 5.4.x to PHP 5.5.x
Migrating from PHP 5.5.x to PHP 5.6.x
Migrating from PHP 5.6.x to PHP 7.0.x


Leave a Comment