PHP 8 New Features
Although PHP 8 was release in 2021, I like to continue staying up to date with as much as I can. Without further ado, here are some cool PHP Features and Snippets. Although enforcing types is not new to PHP it has had some great improvements with primitives (string, boolean, integer) this iteration. Don't get type declarations confused with type casting. Type declarations are added to method arguments, return values and class properties. A type declaration provides tighter control over passing data through PHP in order to reduce bugs. Type casting attempts to change from one to to another (eg: int to string) Here's what type-casting looks like. Changing one type to another, if possible. These have parenthesis around them And here is what type declaration looks like. I'll show you a few things you may already know and we'll expand a bit on this with the new features. Now it gets a little better with Union Types. These allow parameters to be one or several types. What if you had an integer but wanted to allow a float? Keep in mind I am only speaking about primitives. You could do type declarations for OOP for a long time already. This will just help many of the smaller methods tidy up with a stricter code base. If you don't like the Union Types and find declaring 2 or more redundant you can always allow Don't forget just like in Java if your method doesn't return anything you can declare the return type to This is unusual to see for me but you can now use an argument name (the variable definition) and skip over things you don't need. Python had has this feature for ages and looks a bit nicer in python. Nevertheless, we can do this now. This is somewhat similar to the This will check the array keys and they must be in sequential order, from You may have a public property but with You used to have to call We can also have Nullable parameter types which is pretty great. If we wanted to declare a type as a string but at some point had no string data and just passed null we'd be out of luck. But we can use a Since we hopped onto the In the simplified example I mad, a real world example may have many chained events which would requires much more error checking. To resolve this, we can use a When you create a class we always have to define the variables/properties with their scope within the class definition (public, protected, private). At least we should be doing that not just for protecting certain ones and leaving the others public by default but because it makes for splendid code readability. First let's took a way we are all used to. It is a little tedious to declare and assign the same thing times isn't it? Keep in mind this is only two variables, who knows what kind of crazy classes are out there?! Here's the Constructor Property Promotion. I think it could get a bit messy unless it's separated on lines of code. It is a bit strange to read a scoped class variables in a method definition to me still. Since we are looking at methods its worth pointing out that PHP now allows trailing commas in the parameter list. Whether it's a big deal or not I can't say. We've been using They've added a new Table of Contents
Type Declarations
Type Casting
(type)
.<?php
// This is type casting
$ape = (int) 200; // integer
$bit = (string) 200; // string
$pow = (array) "super" // array
// You can always check with:
gettype($ape);
Type Declaration
<?php
// Requires Parameter to be a string
function getName(string $name) {
return $name;
}
// Requires Parameters to be string, and it must return a string.
function getFullName(string $first, string $last): string
{
return "$first $last";
}
Union Types
<?php
// Requires both parameters to be one or the other,
// The return type is also a Union.
function number(int|float $x, int|float $y): int|float
{
return $x + $y;
}
mixed
like below, but in a way defeats the purpose a little bit:<?php
function status(mixed $data): string {
if (is_array($data)) { /** .. do something */}
}
void
. Using Named Arguments
<?php
// A basic method definition
function getEmail(string $email): string {
return $email;
}
// Call the function by the named parameter!
getEmail(email: 'none@none.com');
// Works of BIF also, eg:
$result = htmlspecialchars('<html></html>', double_encode: false);
Return Type: never
void
return type, however the never
type ceases further execution where void
would.function redirect(string $url): never {
header("Location: $url");
exit;
}
array_is_list
0
to n
with no gaps.array_is_list([1, 2, 3]); // true
array_is_list([1, 'cat', 3]); // true
array_is_list([1 => 'pig', 5 => 'cow']); // false, keys are not sequential and does not start with a 0
array_is_list(['name' => 5, 'cat', 3]); // false, key is named
Class Read Only Property
readonly
you can set it and foreget it. It's almost like a private property with a getter and no setter.class Person {
public readonly string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
$person = new Person('John');
$person->name = 'Jane'; // Error, cannot change
Get Current Objects ::Class
$get_class($instance)
to find your calling class name. Now every object has a built in static constant of ::class
.<?php
$obj = new \stdClass();
// Instead of this
echo get_class($obj);
// We can grab the magic constant
echo $obj::class;
Nullable Parameter Types
?
before the type to allow the type or a nullable type.<?php
class House
{
// Adding the "?" mark allows it to be either!
public function __construct(int $id, ?string $name = null)
{
}
}
Null-Safe Method Chaining
null
train we might as well look at another feature that was added. Null-safe chaining is quite elegant and it's similar to JavaScripts object checking with objName?.param
to see if a parameter is set without giving errors.<?php
class UserAdvisor
{
public function setAccount(array $details)
{
$this->details = $details;
return null; // Forgot to return this object, uh oh!
}
public function setLocation(string $location)
{
$this->location = $location;
return $this; // Return "this" class to chain methods
}
}
$advisor = new UserAdvisor();
// This will give us an error!
$advisor->setAccount(['data'])->setLocation('Palm Beach');
?
before the next method chain (just like the nullable parameter type) and we will avoid a world of checking our data as we go through the one-off chain.<?php
// Adding the "?" before the next method does the trick!
$advisor->setAccount(['data'])?->setLocation('Palm Beach');
Constructor Property Promotion
// Common Way of doing Property Instantiation
class Shape
{
// 1. We declare the scope
public int $x;
public int $y;
public function __construct(int $x, int $y)
{
// 2. We set thee class variables
$this->x = $x;
$this->y = $y;
}
}
$shape = new Shape(5, 10);
<?php
// Once constructed $shape->x will be all set in one go.
class Shape
{
// 1. We just
public function __construct(public int $x, public int $y)
{
// (No need to set $this->x or y here)
}
}
$shape = new Shape(25, 25);
Parameter Trailing Commas
<?php
// Notice the trailing "," comma. This is allowed.
function callMe($phone, $areaCode,) {
return;
}
String Starts/Ends With and Contains
strpos('haystack', 'needle') === 1
or substr
to manage of our good old string management toolbox. Here are three new functions added for string.<?php
// These are case sensitive as far as I've tested.
str_starts_with(haystack: 'This is my string', needle: 'T'); // true
str_ends_with('This is my string', 'string'); // true
str_contains('This is my string', 'my'); // true
Match Feature, like Case/Switch
match()
feature that behaves just like a case/switch
statement yet it's easier to write and use quickly.<?php
$result = match ('dog') {
'cat' => 'meow',
'fish' => 'gurggle',
'dog' => 'woof'
}; // Returns 'woof'
Other Notable Features
__toString()
.token_get_all()
.