Array unpacking with string keys
(PHP 7.4) PHP supports array spread operator ( ...
) for array unpacking. An array can be unpacked with another array if the array expression is prefixed with the spread operator. This effectively results in an array_merge
of all arrays in the expression.
$array_1 = ['foo', 'bar'];
$array_2 = ['baz', 'qux'];
$array_unpacked = [...$array_1, ...$array_2, ...['quux']];
$array_merged = array_merge($array_1, $array_2, ['quux']);
var_dump($array_unpacked);
// ['foo', 'bar', 'baz', 'qux', 'quux'];
var_dump($array_merged);
// ['foo', 'bar', 'baz', 'qux', 'quux'];
Prior to (PHP 8.1), the spread operator only supported arrays with numeric keys. Using an array with string key resulted in an error prior to PHP 8.1:
$array = [...['a' => 'foo'], ...['b' => 'bar']];
# Fatal error: Cannot unpack array with string keys in ... on line ...
From (PHP 8.1), array unpacking supports arrays with string keys as well.
$array = [...['a' => 'foo'], ...['b' => 'bar']];
// ['a' => 'foo', 'b' => 'bar'];
source: https://php.watch/versions/8.1/spread-operator-string-array-keys
Enums
(PHP 8.1) Enumerations are a restricting layer on top of classes and class constants, intended to provide a way to define a closed set of possible values for a type.
enum Status
{
case DRAFT;
case PUBLISHED;
case ARCHIVED;
}
class BlogPost
{
public function __construct(
public Status $status,
) {}
}
$post = new BlogPost(Status::DRAFT);
Enum methods
enum Status
{
case DRAFT;
case PUBLISHED;
case ARCHIVED;
public function color(): string
{
return match($this)
{
Status::DRAFT => 'grey',
Status::PUBLISHED => 'green',
Status::ARCHIVED => 'red',
};
}
}
$status = Status::ARCHIVED;
$status->color(); // 'red'
source: https://stitcher.io/blog/php-enums
Promoted Properties
(PHP 8.0) property promotion allows you to combine class fields, constructor definition and variable assignments all into one syntax, in the construct parameter list.
Instead of doing this:
class CustomerDTO
{
public string $name;
public string $email;
public DateTimeImmutable $birth_date;
public function __construct(
string $name,
string $email,
DateTimeImmutable $birth_date
) {
$this->name = $name;
$this->email = $email;
$this->birth_date = $birth_date;
}
}
You would write this:
class CustomerDTO
{
public function __construct(
public string $name,
public string $email,
public DateTimeImmutable $birth_date,
) {}
}
source: https://stitcher.io/blog/constructor-promotion-in-php-8
Readonly Properties
(PHP 8.1) This makes sure that the public properties couldn’t be overwritten at all
class BlogData
{
public function __construct(
public readonly string $title,
public readonly Status $status,
public readonly ?DateTimeImmutable $publishedAt = null,
) {}
}
source: https://stitcher.io/blog/php-81-readonly-properties
(PHP 8.2) Whole class can be made readonly
readonly class BlogData
{
public function __construct(
public string $title,
public Status $status,
public ?DateTimeImmutable $publishedAt = null,
) {}
}
source: https://stitcher.io/blog/readonly-classes-in-php-82
Pure Intersection Types (&)
(PHP 8.1) supports Intersection Types, which allows declaring a type for a parameter, property, or return types and enforce that values belong to all of the declared class/interface types. This is the opposite of Union Types, which allows any of the declared types. PHP 8.1’s implementation of Intersection Types is called “pure” Intersection Types because combining Union Types and Intersection Types in the same declaration is not allowed.
function count_and_iterate(Iterator&\Countable $value) {
foreach($value as $val) {}
count($value);
}
source: https://php.watch/versions/8.1/intersection-types
Never return type
(PHP 8.1) A function/method that is declared with the never
return type indicates that it will never return
a value, and always throws an exception or terminates with a die
/exit
call.
never
return type is similar to the existing void
return type, but the never
type guarantees that the program will terminate or throw. In other words, a function/method declared never
must not call return
at all, not even in the return;
form.
function redirect(string $url): never {
header('Location: ' . $url);
exit();
}
source: https://php.watch/versions/8.1/never-return-type
array_is_list
(PHP 8.1) brings a new function array_is_list
, that returns whether a given array is an array with all sequential integers starting from 0.
In other words, this function returns true
if the given array is semantic list of values; an array with all keys are integers, keys start from 0, with no gaps in between.
array_is_list
function returns true
on empty arrays as well.
array_is_list([]); // true
array_is_list([1, 2, 3]); // true
array_is_list(['apple', 2, 3]); // true
array_is_list(['apple', 'orange']); // true
array_is_list([0 => 'apple', 'orange']); // true
array_is_list([0 => 'apple', 1 => 'orange']); // true
// Key does not start with 0
array_is_list([1 => 'apple', 'orange']); // false
// Keys are not in order
array_is_list([1 => 'apple', 0 => 'orange']); // false
// Non-integer keys
array_is_list([0 => 'apple', 'foo' => 'bar']); false
// Non-sequential keys
array_is_list([0 => 'apple', 2 => 'bar']); false
source: https://php.watch/versions/8.1/array_is_list
First Class Callable
(PHP 8.1) and later supports a new syntax in creating a callable
from within the current scope. With this new syntax, it is easier to create a callable
using the same syntax a function/method is called, instead of using Closure::fromCallable
.
Closure::fromCallable
returns a callable
(Closure
object) from a PHP callable (function name, method, or anonymous function). The first-class callable syntax aims to reduce the boilerplate code of Closure::fromCallable.
// old
$callable = Closure::fromCallable('strtoupper');
// new
$callable = strtoupper(...);
echo $callable('foo'); // FOO
source: https://php.watch/versions/8.1/first-class-callable-syntax
new in initializers
(PHP 8.1) now you can directly initialize a class in default value
class MyStateMachine
{
public function __construct(
private State $state = new InitialState(),
) {
}
}
source: https://stitcher.io/blog/php-81-new-in-initializers
Final Class Constant
(PHP 8.1) Constants declared on PHP classes can be overridden by sub classes. Prior to PHP 8.1, the final
flag was not allowed on class constants, which would have protected class constants from being overridden by sub classes. Attempting to use the final
flag on class constants resulted in a fatal error.
In PHP 8.1 and later, the final
flag is allowed on class/interface constants, and none of the sub classes are allowed to extend/override final
constants.
class Foo {
final public const TEST = '1';
}
class Bar extends Foo {
public const TEST = '2';
}
# Fatal error: Bar::TEST cannot override final constant Foo::TEST in %s on line %d
Leave a Reply