Thursday, November 21, 2024
HomeEveryday WordPressHere’s what’s new and improved

Here’s what’s new and improved


Pumpkin spice is in the air, so it’s time for a new version of PHP, the server-side scripting language that powers our favorite CMS, WordPress. Leading up to the November 21 GA launch of version 8.4, PHP’s developers unveiled numerous early versions of the new codebase, including a handful of release candidates since an August feature freeze.

Along with the new features, improvements, and deprecations, we anticipate this time of year, 2024 saw tweaks to PHP’s release cycle, with the end of security releases for all currently supported versions synced to the end of the year instead of its GA birthday.

What’s more, that support was extended by a year, meaning you could be using PHP 8.4 safely through 2028 (with two years of security and bug fixes and two years of just security fixes).

While you might be able to spend more time with PHP 8.4, you probably want to learn what’s new in this release right now. So, let’s jump in.

New features and improvements in PHP 8.4

The new features included in the release of PHP 8.3 last year will seem low-key when compared to some of the additions found in 8.4:

Property hooks

Property hooks bring a whole new approach to handling “getters” and “setters” in PHP object-oriented programming (OOP), allowing you to simplify the structure of your class files.

As an example of what property hooks can replace, the simple class below includes the properties $size and $flavor. They have private visibility to protect them from direct access outside the resulting object. That’s why public getter and setter methods mediate access to the properties:

class Coffee
{
    private string $size;
    private string $flavor;
    public function __construct(string $size, string $flavor) {
        $this->size   = $size;
        $this->flavor = $flavor;
    }

    // "Setting" coffee size and flavor
    public function setSize(string $size): void {
        $this->size = $size;
    }
    public function setFlavor(string $flavor): void {
        $this->flavor = $flavor;
    }

    // "Getting" coffee size and flavor
    public function getSize(): string {
        return $this->size;
    }
    public function getFlavor(): string {
        return $this->flavor;
    }
} // End of class

// Make some coffee
$coffee = new Coffee('Small', 'Pumpkin Spice');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Small Pumpkin Spice"

// Change order
$coffee->setSize('Grande');
$coffee->setFlavor('Mocha');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Grande Mocha"

Or, maybe your class has many properties, and instead of writing many getter and setter methods, you use PHP’s _get and _set magic methods. You might even sort things out in a somewhat messy switch statement like this excerpt below.

// __set magic method example
public function __set(string $key, $value): void 
    switch ($key) {
        case 'size':
            $this->size = $value;
            break;
        case 'flavor':
            $this->flavor = $value;
            break;
        default:
            throw new InvalidArgumentException('Invalid input');
        }
}

// Later, we can change the coffee order like this:
$coffee->size="Grande";
$coffee->flavor="Mocha";

Whichever approach you choose, the more properties you have in your class, the further the code used to manipulate them will be from their definitions near the top of your class file. What’s more, some implementations of the _get and _set magic methods can unexpectedly provide access to private or protected properties in your object that you hadn’t intended to expose.

The new property hooks feature bundles getter and setter functionality with the properties themselves. In the property hooks example below, you’ll notice that the $size and $flavor properties of the Coffee class are now public. But we’ve also added some basic validation to the set hooks, differentiating them from direct assignments.

// Property definitions at the top of our Coffee class
class Coffee
{
    public string $flavor {
        set(string $value) {
            if (strlen($value) > 16) throw new InvalidArgumentException('Input is too long');
                $this->flavor = $value;
        }
    }

    public string $size {
        set(string $value) {
            if (! in_array($value, array(‘Small’, ‘Grande’))) throw new InvalidArgumentException('Not a valid size');
                $this->size = $value;
        }
    }

    // Rest of the Coffee class
}

// Define a coffee
$coffee = new Coffee();
$coffee->size="Grande";
$coffee->flavor="Pumpkin spice";

Likewise, as you can see below, a get hook can pack functionality into what appears to be an ordinary reference to an object property.

// Simplified Coffee class
class Coffee
{
    public string $flavor {
        get { 
            return $this->flavor . ' Spice';
       }
    }
}

// Create a flavor 
$coffee = new Coffee();
$coffee->flavor="Pumpkin"; // Stores the value "Pumpkin"
print $coffee->flavor;       // Prints "Pumpkin Spice"

Unlike the PHP magic methods, property hooks can be used in interfaces and abstract classes. An interface example:

interface Coffee
{
    public string $size { get; set; }
    public string $flavor { get; set; }
}

Asymmetric visibility

Publicly visible getter and setter methods we looked at earlier represent the traditional approach to accessing private and protected properties within their classes.

A nifty feature of PHP 8.4 is the ability of a property to have different levels of visibility depending on the context in which it is accessed. So, a property might be public when being read but private or protected when being set.

Check this out:

class Coffee
{
    public private(set) string $flavor="Pumpkin Spice";
}

$coffee = new Coffee();
print $coffee->flavor;     // Prints "Pumpkin Spice"
$coffee->flavor="Mocha";  // Error (visibility)

Above, the class’s $flavor property is public except in a setting context. It’s pretty simple already, but asymmetric visibility even has a bit of a shortcut:

class Coffee
{
    // public is assumed when the context is not setting
    private(set) string $flavor="Pumpkin Spice";
}

You can use property hooks and asymmetric visibility in combination for tremendous flexibility in working with object properties of various visibilities.

Chaining new without parentheses

Speaking of shorthands, calling new and chaining methods used to require placing its invocation in parentheses, like this:

$coffee = (new Coffee())->getFlavor()->getSize();

PHP 8.4 allows this:

$coffee = new Coffee()->getFlavor()->getSize();

It may seem like a minor change, but dropping just two parentheses makes that much easier to read and debug.

New functions for finding array items

From the “You mean we couldn’t already do this?” department, PHP 8.4 introduces the function array_find(), which can search array elements for members matching conditions expressed in a callback function. The function returns the value of the first element matching the callback’s test.

The new release includes three other related functions:

  • array_find_key(): Like array_find(), but the return value is the matching element’s key instead of the value of the elements itself.
  • array_all(): Returns true if every element in the array being tested matches the callback’s test.
  • array_any(): Returns true if at least one of the elements in the array matches the callback’s test.

Note that the last two functions return boolean indicators instead of array keys or content.

Here are some quick examples:

$array = [
    'a' => 'Mocha',
    'b' => 'Caramel',
    'c' => 'Maple',
    'd' => 'Pumpkin'
   ];

// Find the first flavor name that is 5 characters long
var_dump(array_find($array, function (string $value) {
    return strlen($value) == 5;
})); // Returns “Mocha,” even though “Maple” is the same length 

// Find the array key for the first flavor with a name longer than 5 characters.
var_dump(array_find_key($array, function (string $value) {
    return strlen($value) > 5;
})); // Returns “b”

// Check to see if any flavor name is less than 5 characters long
var_dump(array_any($array, function (string $value) {
    return strlen($value) 



Source link

RELATED ARTICLES
Continue to the category

LEAVE A REPLY

Please enter your comment!
Please enter your name here


Most Popular

Recent Comments