NexusCS

PHP 7

PHP
Quick reference for PHP 7.0-7.4 new features including type declarations, operators, arrow functions, and more.
php7
featured

Getting started

PHP 7.0 Highlights

Scalar Type Declarations

function add(int $a, int $b): int {
    return $a + $b;
}

add(1, 2);        // 3
add(1.5, 2.5);    // 3 (casted)

Null Coalescing

// Before PHP 7
$name = isset($_GET['name'])
    ? $_GET['name']
    : 'Guest';

// PHP 7.0+
$name = $_GET['name'] ?? 'Guest';

Spaceship Operator

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

usort($arr, fn($a, $b) => $a <=> $b);

PHP 7.1 Highlights

Nullable Types

function getUser(?int $id): ?User {
    if ($id === null) return null;
    return User::find($id);
}

Void Return Type

function log(string $msg): void {
    echo $msg;
    // No return statement
}

Array Destructuring

$data = ['Alice', 30, 'Engineer'];

// Symmetric syntax
[$name, $age, $job] = $data;

PHP 7.4 Highlights

Typed Properties

class User {
    public int $id;
    public string $name;
    private ?DateTime $created = null;
}

Arrow Functions

// Before PHP 7.4
$fn = function($x) {
    return $x * 2;
};

// PHP 7.4+
$fn = fn($x) => $x * 2;

Null Coalescing Assignment

// Before PHP 7.4
$data['key'] = $data['key'] ?? 'default';

// PHP 7.4+
$data['key'] ??= 'default';

Type Declarations (7.0+)

Scalar Types

Type Description
int Integer values
float Floating point numbers
string String values
bool Boolean values

Strict Types

<?php
declare(strict_types=1);

function sum(int $a, int $b): int {
    return $a + $b;
}

sum(1, 2);      // OK
sum(1.5, 2);    // TypeError

Type Coercion (default)

<?php
// No declare statement

function sum(int $a, int $b): int {
    return $a + $b;
}

sum(1, 2);      // 3
sum(1.5, 2.8);  // 3 (coerced)

Return Types

Basic Return Types

function getName(): string {
    return 'John';
}

function getAge(): int {
    return 30;
}

function isActive(): bool {
    return true;
}

Array & Callable

function getItems(): array {
    return [1, 2, 3];
}

function getCallback(): callable {
    return function() { };
}

Class Types

function getUser(): User {
    return new User();
}

function getDateTime(): DateTime {
    return new DateTime();
}

Nullable Types (7.1+)

Nullable Parameters

function greet(?string $name): string {
    return $name ?? 'Guest';
}

greet('Alice');  // "Alice"
greet(null);     // "Guest"

Nullable Returns

function find(int $id): ?User {
    $user = User::findById($id);
    return $user ?: null;
}

$user = find(1);  // User or null

Combined

function process(?array $data): ?string {
    if ($data === null) return null;
    return implode(',', $data);
}

Void Type (7.1+)

Basic Void

function log(string $msg): void {
    file_put_contents('log.txt', $msg);
}

function redirect(string $url): void {
    header("Location: $url");
    exit;
}

Void Cannot Return

function invalid(): void {
    return null;  // Error!
}

function valid(): void {
    return;  // OK
}

Object Type (7.2+)

function setData(object $obj): object {
    $obj->modified = true;
    return $obj;
}

setData(new stdClass());  // OK
setData(new User());      // OK
setData([]);              // TypeError

Iterable Type (7.1+)

function process(iterable $data): void {
    foreach ($data as $item) {
        echo $item;
    }
}

process([1, 2, 3]);           // OK
process(new ArrayIterator()); // OK
process('string');            // TypeError

Typed Properties (7.4+)

Basic Syntax

Property Types

class User {
    public int $id;
    public string $name;
    public bool $active;
    private float $balance;
    protected array $roles;
}

Nullable Properties

class Post {
    public ?string $title = null;
    public ?User $author = null;
    public ?DateTime $published;
}

Default Values

class Config {
    public string $env = 'production';
    public int $timeout = 30;
    public array $options = [];
}

Class Types

class Article {
    public User $author;
    public DateTime $created;
    private Category $category;
}

$article = new Article();
$article->author = new User();  // OK
$article->author = 'string';    // TypeError

Uninitialized State

Error on Access

class User {
    public int $id;
    public string $name;
}

$user = new User();
echo $user->id;  // Error: Uninitialized

Must Initialize

class User {
    public int $id;

    public function __construct(int $id) {
        $this->id = $id;  // Required
    }
}

Visibility Modifiers

class Product {
    public string $name;
    protected float $cost;
    private int $stock;

    public static string $category;
}

Operators

Null Coalescing (??) (7.0+)

Basic Usage

$name = $_GET['name'] ?? 'Guest';
$age = $user->age ?? 0;
$color = $config['color'] ?? 'blue';

Chaining

$value = $a ?? $b ?? $c ?? 'default';

Before PHP 7

// Ternary
$name = isset($_GET['name'])
    ? $_GET['name']
    : 'Guest';

// Short ternary
$name = $_GET['name'] ?: 'Guest';

Null Coalescing Assignment (??=) (7.4+)

Assignment Shorthand

// Before 7.4
$data['key'] = $data['key'] ?? 'default';

// PHP 7.4+
$data['key'] ??= 'default';

Real-World Examples

$_GET['page'] ??= 1;
$config['timeout'] ??= 30;
$cache[$key] ??= expensive_operation();

Difference from ||=

$value = 0;
$value ??= 10;  // 0 (not null)
$value = $value ?: 10;  // 10 (falsy)

Spaceship (<=>) (7.0+)

Three-Way Comparison

$a <=> $b;
// Returns:
// -1 if $a < $b
//  0 if $a == $b
//  1 if $a > $b

Sorting

$numbers = [3, 1, 4, 1, 5];
usort($numbers, fn($a, $b) => $a <=> $b);
// [1, 1, 3, 4, 5]

// Descending
usort($numbers, fn($a, $b) => $b <=> $a);

String Comparison

'a' <=> 'b';  // -1
'z' <=> 'a';  //  1
'x' <=> 'x';  //  0

$names = ['Zoe', 'Alice', 'Bob'];
usort($names, fn($a, $b) => $a <=> $b);
// ['Alice', 'Bob', 'Zoe']

Multi-Field Sorting

usort($users, function($a, $b) {
    return [$a->last, $a->first]
       <=> [$b->last, $b->first];
});

Arrow Functions (7.4+)

Basic Syntax

Short Syntax

// Before 7.4
$fn = function($x) {
    return $x * 2;
};

// PHP 7.4+
$fn = fn($x) => $x * 2;

Array Functions

$numbers = [1, 2, 3, 4, 5];

$doubled = array_map(
    fn($n) => $n * 2,
    $numbers
);

$filtered = array_filter(
    $numbers,
    fn($n) => $n > 2
);

Automatic Capture

By-Value Capture

$multiplier = 3;

// Before 7.4
$fn = function($x) use ($multiplier) {
    return $x * $multiplier;
};

// PHP 7.4+
$fn = fn($x) => $x * $multiplier;

Multiple Variables

$min = 10;
$max = 100;

$validate = fn($x) => $x >= $min && $x <= $max;

Single Expression

Implicit Return

$square = fn($x) => $x * $x;
$greet = fn($name) => "Hello, $name!";
$sum = fn($a, $b) => $a + $b;

Cannot Use Statements

// Invalid
$fn = fn($x) => {
    $result = $x * 2;
    return $result;
};

// Valid - use closure
$fn = function($x) {
    $result = $x * 2;
    return $result;
};

Type Declarations

$typed = fn(int $x): int => $x * 2;

$nullable = fn(?string $s): string =>
    $s ?? 'default';

$complex = fn(User $u): ?string =>
    $u->getName();

Real-World Examples

Sorting

usort($users, fn($a, $b) =>
    $a->getName() <=> $b->getName()
);

Filtering

$adults = array_filter(
    $people,
    fn($p) => $p->age >= 18
);

Mapping

$names = array_map(
    fn($user) => $user->name,
    $users
);

Reduce

$total = array_reduce(
    $items,
    fn($carry, $item) => $carry + $item->price,
    0
);

Array Features

Array Destructuring (7.1+)

Symmetric Syntax

$data = ['Alice', 30, 'Engineer'];

// PHP 7.1+
[$name, $age, $job] = $data;

// Still valid
list($name, $age, $job) = $data;

Skipping Elements

[$name, , $job] = ['Alice', 30, 'Engineer'];
// $name = 'Alice', $job = 'Engineer'

Nested Arrays

$data = ['Alice', [30, 'Engineer']];
[$name, [$age, $job]] = $data;

Keys in List (7.1+)

Associative Arrays

$user = [
    'name' => 'Alice',
    'age' => 30,
    'job' => 'Engineer'
];

['name' => $name, 'age' => $age] = $user;

Mixed Keys

$data = ['id' => 1, 'Alice', 'email' => 'a@ex.com'];

['id' => $id, $name, 'email' => $email] = $data;

Foreach Destructuring

List Syntax

$users = [
    ['Alice', 30],
    ['Bob', 25],
];

foreach ($users as [$name, $age]) {
    echo "$name is $age years old\n";
}

Keyed Destructuring

$users = [
    ['name' => 'Alice', 'age' => 30],
    ['name' => 'Bob', 'age' => 25],
];

foreach ($users as ['name' => $n, 'age' => $a]) {
    echo "$n is $a years old\n";
}

References in Destructuring (7.3+)

$array = [1, 2, 3];
[$a, &$b] = $array;

$b = 10;
// $array is now [1, 10, 3]

Array Unpacking (7.4+)

Spread Operator

$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];

$merged = [...$arr1, ...$arr2];
// [1, 2, 3, 4, 5, 6]

With Keys

$defaults = ['a' => 1, 'b' => 2];
$custom = ['b' => 3, 'c' => 4];

$config = [...$defaults, ...$custom];
// ['a' => 1, 'b' => 3, 'c' => 4]

Before 7.4

$merged = array_merge($arr1, $arr2);

Class Features

Anonymous Classes (7.0+)

Basic Syntax

$logger = new class {
    public function log($msg) {
        echo $msg;
    }
};

$logger->log('Hello');

With Constructor

$util = new class($dep) {
    private $dependency;

    public function __construct($dep) {
        $this->dependency = $dep;
    }

    public function doSomething() {
        return $this->dependency->process();
    }
};

Implementing Interfaces

$handler = new class implements Handler {
    public function handle($request) {
        // Implementation
    }
};

Extending Classes

$custom = new class extends BaseClass {
    public function customMethod() {
        return parent::baseMethod() . ' extended';
    }
};

Class Constant Visibility (7.1+)

Visibility Modifiers

class Config {
    public const PUBLIC_KEY = 'public';
    protected const PROTECTED_KEY = 'protected';
    private const PRIVATE_KEY = 'private';
}

echo Config::PUBLIC_KEY;  // OK
echo Config::PRIVATE_KEY; // Error

Inheritance

class Base {
    protected const VALUE = 10;
}

class Child extends Base {
    public function getValue() {
        return self::VALUE;  // OK
    }
}

echo Child::VALUE;  // Error (protected)

Covariance & Contravariance (7.4+)

Return Type Covariance

interface Factory {
    public function create(): object;
}

class UserFactory implements Factory {
    // More specific return type
    public function create(): User {
        return new User();
    }
}

Parameter Type Contravariance

interface Validator {
    public function validate(User $user): bool;
}

class AdminValidator implements Validator {
    // More general parameter type
    public function validate(object $obj): bool {
        return $obj instanceof User &&
               $obj->isAdmin();
    }
}

Exception Handling

Throwable Interface (7.0+)

Hierarchy

interface Throwable {
    // Base interface
}

class Error implements Throwable {
    // Internal errors
}

class Exception implements Throwable {
    // User exceptions
}

Catching All

try {
    // Code
} catch (Throwable $e) {
    // Catches Error AND Exception
}

Error Hierarchy (7.0+)

Error
├── ArithmeticError
│   └── DivisionByZeroError
├── AssertionError
├── ParseError
└── TypeError

Catching Errors

try {
    $result = 1 / 0;
} catch (DivisionByZeroError $e) {
    echo "Cannot divide by zero";
}

try {
    require 'invalid.php';
} catch (ParseError $e) {
    echo "Parse error: " . $e->getMessage();
}

Multi-Catch (7.1+)

Single Handler

try {
    // Code
} catch (IOException | NetworkException $e) {
    log($e);
}

Multiple Handlers

try {
    // Code
} catch (ValidationException | InvalidInputException $e) {
    return response()->json(['error' => $e->getMessage()], 400);
} catch (NotFoundException $e) {
    return response()->json(['error' => 'Not found'], 404);
} catch (Exception $e) {
    return response()->json(['error' => 'Server error'], 500);
}

Syntax Improvements

Group Use Declarations (7.0+)

Before PHP 7

use Framework\Component\ClassA;
use Framework\Component\ClassB;
use Framework\Component\ClassC;

PHP 7.0+

use Framework\Component\{
    ClassA,
    ClassB,
    ClassC
};

Mixed Types

use Framework\Component\{
    ClassA,
    ClassB,
    function helper,
    const CONFIG
};

Heredoc/Nowdoc (7.3+)

Flexible Indentation

// Before 7.3 - must be at column 0
$html = <<<HTML
<div>
    <p>Content</p>
</div>
HTML;

// PHP 7.3+ - can indent
$html = <<<HTML
    <div>
        <p>Content</p>
    </div>
    HTML;

Trailing Comma

$sql = <<<SQL
    SELECT *
    FROM users
    WHERE active = 1
    SQL;

Trailing Commas (7.2-7.3)

Function Calls (7.3+)

$result = myFunction(
    $arg1,
    $arg2,
    $arg3,  // Trailing comma OK
);

Arrays (Always)

$data = [
    'name' => 'Alice',
    'age' => 30,
    'job' => 'Engineer',  // Always OK
];

Not in Declarations

// Still invalid
function test(
    $arg1,
    $arg2,  // Error!
) {
}

Numeric Literal Separator (7.4+)

Readability

$million = 1_000_000;
$billion = 1_000_000_000;
$pi = 3.141_592_653_589;
$binary = 0b0101_1111;
$hex = 0xFF_EC_DE_5E;

Ignored in Value

1_000 == 1000;  // true
1_2_3 == 123;   // true

Generators

Generator Return (7.0+)

Return Value

function count_to($max) {
    for ($i = 1; $i <= $max; $i++) {
        yield $i;
    }
    return $max;
}

$gen = count_to(5);
foreach ($gen as $num) {
    echo $num;  // 1, 2, 3, 4, 5
}
echo $gen->getReturn();  // 5

Combined Results

function process() {
    $sum = 0;
    for ($i = 1; $i <= 10; $i++) {
        yield $i;
        $sum += $i;
    }
    return $sum;
}

Generator Delegation (7.0+)

Yield From

function gen1() {
    yield 1;
    yield 2;
}

function gen2() {
    yield 3;
    yield 4;
}

function combined() {
    yield from gen1();
    yield from gen2();
}

// Outputs: 1, 2, 3, 4
foreach (combined() as $num) {
    echo $num;
}

Array Delegation

function numbers() {
    yield from [1, 2, 3];
    yield from range(4, 6);
}

Password Hashing

Argon2 Support (7.2+)

Argon2i (7.2+)

$hash = password_hash(
    'secret',
    PASSWORD_ARGON2I
);

password_verify('secret', $hash);  // true

Argon2id (7.3+)

$hash = password_hash(
    'secret',
    PASSWORD_ARGON2ID,
    ['memory_cost' => 2048, 'time_cost' => 4, 'threads' => 3]
);

Custom Options

$options = [
    'memory_cost' => 1024,  // KiB
    'time_cost' => 2,
    'threads' => 2,
];

$hash = password_hash(
    'password',
    PASSWORD_ARGON2ID,
    $options
);

Migration Guide

PHP 5 to 7 Changes

Type Hints

// PHP 5
function add($a, $b) {
    return $a + $b;
}

// PHP 7
function add(int $a, int $b): int {
    return $a + $b;
}

Error Handling

// PHP 5
try {
    // Code
} catch (Exception $e) {
    // Only catches Exception
}

// PHP 7
try {
    // Code
} catch (Throwable $e) {
    // Catches Error AND Exception
}

Null Handling

// PHP 5
$name = isset($user['name']) ? $user['name'] : 'Guest';

// PHP 7.0
$name = $user['name'] ?? 'Guest';

// PHP 7.4
$config['key'] ??= 'default';

Common Gotchas

Strict Types

<?php
declare(strict_types=1);  // File-level

function test(int $x) { }

test('10');  // TypeError in strict mode

Uninitialized Properties

class User {
    public int $id;  // Must initialize!
}

$user = new User();
echo $user->id;  // Error: Uninitialized

Void Returns

function log($msg): void {
    echo $msg;
    return null;  // Error!
}

Arrow Function Limitations

// Cannot use statements
$fn = fn($x) => {  // Error!
    $y = $x * 2;
    return $y;
};

// Use closure instead
$fn = function($x) {
    $y = $x * 2;
    return $y;
};

Performance Improvements

PHP 7.0 vs PHP 5.6

Speed Improvements

  • 2x faster execution
  • 50% less memory usage
  • Better opcode caching

Benchmarks

# WordPress (requests/sec)
PHP 5.6: 49
PHP 7.0: 97 (+98%)

# Drupal (requests/sec)
PHP 5.6: 18
PHP 7.0: 35 (+94%)

Optimization Tips

Use Type Declarations

// Slower
function process($data) {
    return count($data);
}

// Faster
function process(array $data): int {
    return count($data);
}

Preload (7.4+)

// php.ini
opcache.preload=/path/to/preload.php

// preload.php
<?php
opcache_compile_file('app/User.php');
opcache_compile_file('app/Post.php');

Also see