You should now start using the 10 PHP 8.1 features

Posted by icecube on Mon, 06 Dec 2021 19:50:12 +0100

PHP 8.1 is now available with new features and performance improvements -- the most exciting is the new JIT compiler. It was recently released on November 25, 2021.

I'll demonstrate in detail the top 10 features provided by PHP 8.1 so that you can start using them in your projects and improve your PHP experience. Beginners and experienced developers can benefit from this article.

Top 10 functions provided by PHP 8.1

  1. enumeration
  2. fibre
  3. Never return type
  4. Read only attribute
  5. Final class constant
  6. New "array_is_list()" function
  7. New "fsync()" and "fdatasync()" functions
  8. Array unpacking support for string keyed arrays
  9. New "full_path" key in "$_FILES" for directory upload
  10. New "IntlDatePatternGenerator" class

1. Enumeration

PHP 8.1 adds support for enumeration, also known as enumeration. It is an itemized type that contains a fixed number of possible values. See the following code snippet for how to use enumeration.

<?php

/**
 * Declare an enumeration.
 * It can also contain an optional 'string' or 'int' value. This is called backed Enum.
 * Backed enums (if used) should match the following criteria:
 * - Declare the scalar type, whether string or int, in the Enum declaration.
 * - All cases have values.
 * - All cases contain the same scalar type, whether string or int.
 * - Each case has a unique value.
 */
enum UserRole: string {
    case ADMIN    = '1';
    case GUEST    = '2';
    case WRITER   = '3';
    case EDITOR   = '4';
}

/**
 * You can access a case by using
 * the '::' scope resolution operator.
 * And, to get the name of the enum case, you
 * can use the '->' followed by the attribute 'name'.
 */
echo UserRole::WRITER->name;

/**
 * To get the value of the enum case, you can
 * use the '->' followed by the attribute 'value'.
 */
echo UserRole::WRITER->value;

?>

2. Fiber

PHP 8.1 adds support for Fibers, a low-level component that allows concurrent code execution in PHP. Fiber is a code block that contains its own variables and state stack. These Fibers can be considered application threads and can be started from the main program. Once started, the main program cannot suspend or terminate fiber. It can only pause or terminate from within the fiber code block. After the fiber is suspended, control returns to the main program again, and it can continue to execute the fiber from the suspended point.

Fiber itself does not allow multiple fibers or the main thread and a fiber to be executed at the same time. However, for the PHP framework, managing the execution stack efficiently and allowing asynchronous execution is a huge advantage.

See the following code snippet to learn how to use Fibers.

<?php

/**
 * Initialize the Fiber.
 */
$fiber = new Fiber(function(): void {
    /**
     * Print some message from inside the Fiber.
     * Before the Fiber gets suspended.
     */
    echo "Welcome to Fiber!\n";
    /**
     * Suspend the Fiber.
     */
    Fiber::suspend();
    /**
     * Print some message from inside the Fiber.
     * After the Fiber gets resumed.
     */
    echo "Welcome back to Fiber!\n";
});

/**
 * Print a message before starting a Fiber.
 */
echo "Starting a Fiber\n";
/**
 * Start the Fiber.
 */
$fiber->start();
/**
 * Fiber has been suspened from the inside.
 * Print some message, and then resume the Fiber.
 */
echo "Fiber has been suspended\n";
echo "Resuming the Fiber\n";
/**
 * Resume the Fiber.
 */
$fiber->resume();
/**
 * End of the example.
 */
echo "Fiber completed execution\n";

?>

3. "Never" return type

PHP 8.1 adds a pair named never. This never type can be used to indicate that the function will terminate program execution after executing a specified set of tasks. This can be done by throwing an exception and calling the exit() or die() function.

The never return type is similar to the void return type. However, the void return type continues after the function completes a specified set of tasks.

See the following code snippet for how to use the never return type.

<?php

/**
 * Route Class
 */
class Route {

    /**
     * Constructor of the class
     * @return void
     */
    public function __construct() {

    }

    /**
     * Redirect To a Page
     * This function redirects to an URL specified by the user.
     * @method redirect()
     * @param string $url
     * @param integer $httpCode
     * @author Tara Prasad Routray <someemailaddress@example.com>
     * @access public
     * @return never
     */
    public static function redirect($url, $httpCode = 301): never {
        /**
         * Redirect to the URL specified.
         */
        header("Location: {$url}", true, $httpCode);
        die;
    }
}

Route::redirect('https://www.google.com');

?>

4. Read only attribute

PHP 8.1 adds that the class attribute named readonly. Declared as read-only can only be initialized once. The value set inside cannot be changed. If you try to forcibly update the value, the application will throw an error. See the following code snippet to learn how to use read-only attributes.

<?php

/**
 * User Class
 */
class User {
    /**
     * Declare a variable with readonly property.
     * @var $authUserID
     * @access public
     */
    public readonly int $authUserID;
    /**
     * Constructor of the class.
     * @param integer $userID
     * @return void
     */
    public function __construct($userID) {
        /**
         * Change the value of the property as specified.
         * Updating the value of readonly properties are
         * allowed only through the constructor.
         */
        $this->authUserID = $userID;
    }
    /**
     * Update Auth User ID
     * This function tries to update the readonly property (which is not allowed).
     * @method updateAuthUserID()
     * @param integer $userID
     * @author Tara Prasad Routray <someemailaddress@example.com>
     * @access public
     * @return void
     */
    public function updateAuthUserID($userID) {
        /**
         * Change the value of the property as specified.
         * Executing this function will throw the following error;
         * PHP Fatal error:  Uncaught Error: Cannot modify readonly property User::$authUserID
         */
        $this->authUserID = $userID;
    }
}
/**
 * Initialize the class and update the value of the readonly property.
 */
$user = new User(30);
/**
 * Print the readonly property value.
 * This will print 30.
 */
echo $user->authUserID;
/**
 * Call another function inside the class and try to update the class property.
 */
$user->updateAuthUserID(50);
/**
 * Print the readonly property value.
 */
echo $user->authUserID;

?>

5. Final class constant

PHP 8.1 adds support for a new flag for a class constant named final. Finally, class constants cannot be modified, even through inheritance, which means that they cannot be extended or overridden by subclasses.

This flag cannot be used for private constants because it cannot be accessed outside the class. Declaring final and private constants will result in fatal errors.

See the following code snippet for how to use the final flag.

<?php

/**
 * UserRole Class
 */
class UserRole {
    /**
     * Declare a final class constant with a value.
     */
    final public const ADMIN = '1';
}

/**
 * User Class extending the UserRole Class
 */
class User extends UserRole {
    /**
     * Declare another constant with the same name
     * as of the parent class to override the value.
     * 
     * Note: Overriding the value will throw the following error:
     * PHP Fatal error:  User::ADMIN cannot override final constant UserRole::ADMIN
     */
    public const ADMIN = '2';
}

?>

6. New 'array'_ is_ List() 'function

PHP 8.1 adds a pair named array_is_list(). It identifies whether the specified array has all consecutive integers starting from 0. If the array is a semantic list of values (an array whose keys start from 0, are integers, and there is no gap between them), this function returns true. It also returns true for an empty array. See the following code snippet to learn how to use array_is_list() function.

<?php

/**
 * Returns true for empty array.
 */
array_is_list([]);
/**
 * Returns true for sequential set of keys.
 */
array_is_list([1, 2, 3]);
/**
 * Returns true as the first key is zero, and keys are in sequential order.
 * It is same as [0 => 'apple', 1 => 2, 2 => 3]
 */
array_is_list(['apple', 2, 3]);
/**
 * Returns true as the first key is zero, and keys are in sequential order.
 * It is same as [0 => 'apple', 1 => 'scissor']
 */
array_is_list(['apple', 'orange']);
/**
 * Returns true as the first key is zero, and keys are in sequential order.
 * It is same as [0 => 'apple', 1 => 'scissor']
 */
array_is_list([0 => 'apple', 'orange']);
/**
 * Returns true as the first key is zero, and keys are in sequential order.
 */
array_is_list([0 => 'rock', 1 => 'scissor']);

?>

Arrays where the key is not a zero based array, or the key is not an integer, or the key is an integer but does not appear in order will be evaluated as false.

<?php

/**
 * Returns false as the first key does not start from zero.
 */
array_is_list([1 => 'apple', 'orange']);
/**
 * Returns false as the first key does not start from zero.
 */
array_is_list([1 => 'apple', 0 => 'orange']);
/**
 * Returns false as all keys are not integer.
 */
array_is_list([0 => 'apple', 'fruit' => 'orange']);
/**
 * Returns false as the keys are not in sequential order.
 */
array_is_list([0 => 'apple', 2 => 'orange']); 

?>

7. New "fsync()" and "fdatasync()" functions

PHP 8.1 adds support for the fsync () and fdatasync () functions. Both are similar to the existing fflush() function, which is currently used to flush buffers into the operating system. However, fsync () and fdatasync () flush the buffer to physical storage. The only difference between them is that the fsync() function contains metadata when synchronizing file changes, while the fdatasync() function does not contain metadata.

The fsync() function takes the file pointer and attempts to commit the changes to disk. Returns true on success and false on failure. If the resource is not a file, a warning will be issued. The fdatasync() function works the same way, but it is a little faster, because fsync () will try to fully synchronize the data changes of the file and the metadata about the file (last modification time, etc.), which is technically two disk writes.

See the following code snippet for how to use the fsync() and fdatasync() functions.

<?php

/**
 * Declare a variable and assign a filename.
 */
$fileName = 'notes.txt';
/**
 * Create the file with read and write permission.
 */
$file = fopen($fileName, 'w+');
/**
 * Add some text into the file.
 */
fwrite($file, 'Paragraph 1');
/**
 * Add a line break into the file.
 */
fwrite($file, "\r\n");
/**
 * Add some more text into the file.
 */
fwrite($file, 'Paragraph 2');
/**
 * You can use both the fsync() or fdatasync() functions 
 * to commit changs to disk.
 */
fsync($file); // or fdatasync($file).
/**
 * Close the open file pointer.
 */
fclose($file);

?>

8. Array unpacking support for string keyed arrays

PHP 8.1 adds support for unpacking string key arrays. To decompress the array, PHP uses the expand (...) operator. PHP 7.4 introduces this operator to combine two or more arrays, but the syntax is more concise. But before PHP 8.1, the expansion operator only supported arrays with numeric keys. See the following code snippet to learn how to use the expansion operator with string keyed arrays.

<?php

/**
 * Declare an array
 */
$fruits1 = ['Jonathan Apples', 'Sapote'];
/**
 * Declare another array
 */
$fruits2 = ['Pomelo', 'Jackfruit'];
/**
 * Merge above two arrays using array unpacking.
 */
$unpackedFruits = [...$fruits1, ...$fruits2, ...['Red Delicious']];
/**
 * Print the above unpacked array.
 * This will print:
 * array(5) {
 * [0]=>
 * string(15) "Jonathan Apples"
 * [1]=>
 * string(6) "Sapote"
 * [2]=>
 * string(6) "Pomelo"
 * [3]=>
 * string(9) "Jackfruit"
 * [4]=>
 * string(13) "Red Delicious"
 * }
 */
var_dump($unpackedFruits);

?>

9. New 'full'_ Path type$_ FILES' for directory upload

PHP 8.1 add full_path yes$_ Support for new keys in FILES global variables. Before PHP 8.1$_ FILES does not have a relative path or exact directory to store to the server. Therefore, you cannot upload the entire directory using the HTML file upload form. New full_ The path key solves this problem. It stores relative paths and rebuilds the exact directory structure on the server, making directory upload possible. See the following code snippet to learn how to use full_path key and$_ FILES global variable.

<?php

/**
 * Check if the user has submitted the form.
 */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    /**
     * Print the $_FILES global variable. This will display the following:
     * array(1) {
     *   ["myfiles"]=> array(6) {
     *     ["name"]=> array(2) {
     *       [0]=> string(9) "image.png"
     *       [1]=> string(9) "image.png"
     *     }
     *     ["full_path"]=> array(2) {
     *       [0]=> string(25) "folder1/folder2/image.png"
     *       [1]=> string(25) "folder3/folder4/image.png"
     *     }
     *     ["tmp_name"]=> array(2) {
     *       [0]=> string(14) "/tmp/phpV1J3EM"
     *       [1]=> string(14) "/tmp/phpzBmAkT"
     *     }
     *     // ... + error, type, size
     *   }
     * }
     */
    var_dump($_FILES);
}

?>

<form action="" method="POST" enctype="multipart/form-data">
    <input name="myfiles[]" type="file" webkitdirectory multiple />
    <button type="submit">Submit</button>
</form>

10. New "IntlDatePatternGenerator" class

PHP 8.1 adds support for the new IntlDatePatternGenerator class. Before PHP 8.1, only IntlDateFormatter could be used. It supports eight predefined formats used yesterday, today and tomorrow. But these formats are not like IntlDatePatternGenerator. This class allows you to specify the format of date, month and time, and the order will be handled automatically by the class. See the following code snippet to learn how to use the IntlDatePatternGenerator class.

<?php

/**
 * Define a default date format.
 */
$skeleton = "YYYY-MM-dd";
/**
 * Parse a time string (for today) according to a specified format.
 */
$today = \DateTimeImmutable::createFromFormat('Y-m-d', date('Y-m-d'));
/**
 * ===========================
 * PRINTING DATE IN USA FORMAT
 * ===========================
 * Initiate an instance for the IntlDatePatternGenerator class
 * and provide the locale information.
 * In the below example, I've used locale: en_US.
 */ 
$intlDatePatternGenerator = new \IntlDatePatternGenerator("en_US");
/**
 * Get the correct date format for the locale: en_US.
 * Following function "getBestPattern" will return:
 * MM/dd/YYYY
 */
$enUSDatePattern = $intlDatePatternGenerator->getBestPattern($skeleton);
/**
 * Use the "formatObject" function of IntlDateFormatter to print as per specified pattern.
 * This will print the following:
 * Date in en-US: 12/03/2021
 */
echo "Date in en-US: ". \IntlDateFormatter::formatObject($today, $enUSDatePattern, "en_US"). "\n";

/**
 * =============================
 * PRINTING DATE IN INDIA FORMAT
 * =============================
 * Initiate an instance for the IntlDatePatternGenerator class
 * and provide the locale information.
 * In the below example, I've used locale: en_IN.
 */
$intlDatePatternGenerator = new \IntlDatePatternGenerator("en_IN");
/**
 * Get the correct date format for the locale: en_IN.
 * Following function "getBestPattern" will return:
 * dd/MM/YYYY
 */
$enINDatePattern = $intlDatePatternGenerator->getBestPattern($skeleton);
/**
 * Use the "formatObject" function of IntlDateFormatter to print as per specified pattern.
 * This will print the following:
 * Date in en-IN: 03/12/2021
 */
echo "Date in en-IN: ". \IntlDateFormatter::formatObject($today, $enINDatePattern, "en_IN"). "\n";

?>

honor! You have completed the study of the functions provided by PHP 8.1. Now you can continue and start implementing the above functions in your current or upcoming projects.

Original text: levelup.gitconnected.com/top-10-ph...

Topics: PHP