Hunter Skrasek
Thanks to release managers Joe Watkins, Ben Ramsey, and Patrick Allert
Also, 8.1.1RC1 dropped December 3rd, for folks who don't believe in .0 releases
enum Status // singleton; Status::Active === Status::Active { case Active; case Expired; case Cancelled; case Pending; public function isActive(): bool {} // can be static // Look ma, no constants! }
enum Status: string // can be int { // can implement JsonSerializeable case Active = 'active'; case Expired = 'expired'; case Cancelled = 'cancelled'; case Pending = 'pending'; } // can't be used as array keys...for now json_serialize(Status::Active); // 'active' Status::Active->value; // 'active' Status::from('active'); // Status::Active Status::tryFrom('activv'); // null; would throw on ::from
interface HasColor { public function getColor(): Color; } enum Status implements HasColor { // cases go brr public function getColor(): Color {} // Can also include traits, but no properties }
class ValueObject { public function __construct( public readonly string $value ) {} } $foo = new ValueObject('foo'); echo $foo->value; // foo $foo->value = 'bar'; // throws
$foo = $this->foo(...); // instead of [$this, 'foo']; $fn = strlen(...); // instead of Closure::fromCallable('strlen');
Old: class Service { public function __construct(protected Logger = null) { $this->logger ??= new Logger(); } } New: class Service { public function __construct( protected Logger = new Logger() ) {} }
function process( HasId&HasName $item ): Result&ArrayAccess { // do stuff }
You could extend interfaces and then implement the extended interfaces, but this lets you get the same effect without touching the implementation classes at all.
function throwThings(): never { throw new \RuntimeException('things'); } // Different from void return type since it never returns
This helps with static analysis, for detecting dead code. The "never" type also applies to functions that die or trigger errors 100% of the time.
class Base { public const NAME = 'Base'; final public const STATUS_ACTIVE = 'active'; // lets your constants actually be constant } class Extended extends Base { public const NAME = 'Extended'; // works public const STATUS_ACTIVE = 'passive'; // fails }
016 === 16; // false 016 === 14; // true 0o16 === 14; // true 0x16 === 22; // true
$fiber = new Fiber(function (): void {
$valueAfterResuming = Fiber::suspend('after suspending');
// …
});
$valueAfterSuspending = $fiber->start();
$fiber->resume('after resuming');
You'll use these in an event loop, e.g. React/AMPHP. This is not parallel processing
$array1 = ["a" => 1]; $array2 = ["b" => 2]; $array = ["a" => 0, ...$array1, ...$array2]; var_dump($array); // ["a" => 1, "b" => 2]
This follows array_merge semantics