What’s New In PHP 8.1

Paulund
3 min readNov 27, 2021

On the 25th November 2021 the latest version of PHP was released PHP 8.1, let’s have a look at some of the new features included in the release and how it can help you with your development.

  • Enumerations
  • Readonly properties
  • Fibers
  • Pure interestion types
  • never return type
  • First class callable syntax
  • final modifier for class contacts
  • fsync and fdatasync functions
  • array_is_list function
  • Explicit Octal numeral notation
  • New Initializers

Enumerations

Enumerations allow you to define a custom type that can be limited to a specific number of values.

They are useful to use in the scenario where you want to restrict a type value to a specific list of values.

For example, in Blog applications, you might have different types of posts, such as post, page or custom types.

In your code, you might have something like a static defined on your post object of type to define these values.

class Blog
{
const TYPES = [
'BLOG' => 1,
'PAGE' => 2,
'CUSTOM' => 3,
];
}

You can access these in your code by using Blog::TYPES[‘BLOG’].

Now with PHP, you can use an Enum class for these values.

enum BlogTypes
{
case Blog;
case Page;
case Custom;
}

The better of this is now you can strongly type these values in a function.

function validateBlogType(BlogTypes $blogTypes)
{
//
}

$value = BlogTypes:Blog;

validateBlogType($value); // valid method call

validateBlogType('Blog'); // This to return Error of $blogTypes must be of type BlogTypes

Cases by default are not backed by a scalar value, each case is backed by a singleton object for that case name.

echo BlogTypes::Blog; // Prints "Blog"

Enums also allow you to add methods you can use on to return additional information about the cases.

enum BlogTypes
{
case Blog;
case Page;
case Custom;

public function titlePrefix()
{
if ($this === BlogTypes::Page) {
return 'Page - ';
}
return '';
}
}

echo BlogTypes::Blog->titlePrefix(); // return nothing
echo BlogTypes::Page->titlePrefix(); // return Page -

Enums implement an interface of UnitEnum which has a cases method that can be used to fetch all of the cases on an enum.

var_dump(BlogTypes::cases());

array(4) {
[0]=>
enum(BlogTypes::Blog)
[1]=>
enum(BlogTypes::Page)
[2]=>
enum(BlogTypes::Custom)
}

Read Only Properties

Read only properties allows you to define strict rules to change the value of the class properties.

In the past if you wanted to create readonly properties you would create a class that only has a get method and no set method, like this.

class BlogData
{
private Status $status;

public function __construct(Status $status)
{
$this->status = $status;
}

public function getStatus(): Status
{
return $this->status;
}
}

In PHP 8.1 you can do without having to create the getter method.

class BlogData
{
public readonly Status $status;

public function __construct(Status $status)
{
$this->status = $status;
}
}

A good use case for this are for data transfer objects where you don’t want to change the values of the properties of a class once the values have been set.

Never Return Type

A never return type will indicate that a function will never return a value and will either throw an exception or exit the function. This differs to a void return that indicates that the function doesn't return anything.

function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}

First-class Callable Syntax

Previous you can run a callable function by defining it like this.

$foo = [$this, 'foo'];

With PHP 8.1 you can call this method directly with.

$foo = $this->foo();

Final Modifier For Class Constants

Final modifier has been used on classes for some time now but with PHP 8.1 we can now use the final keyword on constants to stop child classes from overriding the parent constant.

class Foo
{
public const XX = "foo";
}

class Bar extends Foo
{
public const XX = "bar"; // No error
}
class Foo
{
final public const XX = "foo";
}

class Bar extends Foo
{
public const XX = "bar"; // Fatal error
}

New Initializers

Objects can now be used as default parameters values, this makes it very easy to use the nullable design pattern in defining classes.

Before you would have to change the default value in the constructor and initialise the default object.

class Service
{
private Logger $logger;

public function __construct(?Logger $logger = null) {
$this->logger = $logger ?? new NullLogger();
}
}

Now we can define this in the parameter list.

class Service
{
private Logger $logger;

public function __construct(Logger $logger = new NullLogger()) {
$this->logger = $logger;
}
}

Originally published at https://paulund.co.uk.

--

--