PHP8.1新特性

枚举(Enumerations)

PHP 8.1使用enum枚举类型来取代一组常量,并获得开箱即用的验证。

<?php

enum UserRole: string
{
    case ADMIN    = "1";
    case GUEST    = "2";
    case WRITER   = "3";
    case EDITOR   = "4";
}

fprintf(STDOUT, "我的名字:%s\n", UserRole::WRITER->name);
fprintf(STDOUT, "我的只:%s\n", UserRole::WRITER->value);

if(UserRole::WRITER instanceof UserRole){
    echo "我属于 \n";
}

if(!"1" instanceof UserRole){
    echo "我不属于 \n";
}

function test(UserRole $role): void
{
    echo "参数限制";
}

只读属性(Readonly Properties)

在PHP 8.1中,只读属性不能在初始化后更改,需先给它们进行赋值,可用于对值对象和数据传输对象建模。如果尝试强行更新该值,应用程序将抛出错误。

<?php

/**
* User Class
*/
class User
{
    /**
     * Declare a variable with readonly property.
     * @var int $authUserID
     * @access public
     */
    public readonly int $authUserID;
    /**
     * Constructor of the class.
     * @param integer $userID
     * @return void
     */
    public function __construct(int $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
     * @return void
     *@author Tara Prasad Routray <someemailaddress@example.com>
     * @access public
     */
    public function updateAuthUserID(int $userID): void
    {
        /**
         * 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;

纤程(Fibers)

PHP 8.1 添加了对 Fiber 的支持,这是一个低级组件,允许在 PHP 中执行并发代码。Fiber 是一个代码块,它包含自己的变量和状态堆栈。这些 Fiber 可以被视为应用程序线程,可以从主程序启动。
一旦启动,主程序将无法挂起或终止 Fiber。它只能从 Fiber 代码块内部暂停<或终止。在 Fiber 挂起后,控制权再次返回到主程序,它可以从挂起的点继续执行 Fiber。
Fiber 本身不允许同时执行多个 Fiber 或主线程和一个 Fiber。但是,对于 PHP 框架来说,高效管理执行堆栈并允许异步执行是一个巨大的优势。

<?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";
    /**
     * 暂停 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";
/**
* 恢复 the Fiber.
*/
$fiber->resume();
/**
* End of the example.
*/
echo "Fiber completed execution\n";

Never返回类型(Never return type)

PHP 8.1 添加了名为 never 的返回类型。该 never 类型可用于指示函数将在执行一组指定的任务后终止程序执行。这可以通过抛出异常、调用 exit() 或 die() 函数来完成。
never 返回类型类似于 void 返回类型。但是,void 返回类型在函数完成一组指定的任务后继续执行。

<?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(string $url, int $httpCode = 301): never
    {
        /**
         * Redirect to the URL specified.
         */
        header("Location: {$url}", true, $httpCode);
        die;
    }
}

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

Final类常量(Final class constants)

PHP 8.1 添加了对名为 final 的类常量的支持。最终类常量不能被修改,即使是通过继承,这意味着它们不能被子类扩展或覆盖。
这个标志不能用于私有常量,因为它不能在类之外被访问。声明 final 和 private 常量将导致致命错误。

<?php

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

/**
* UserAct Class extending the UserIde Class
*/
class UserAct extends UserIde
{
    /**
     * 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';
}

echo UserIde::ADMIN;
echo UserAct::ADMIN;

array_is_list() 函数

PHP 8.1 添加了名为 array_is_list() 的数组函数。它标识指定的数组是否具有从 0 开始的所有连续整数。如果数组是值的语义列表(一个数组,其键从 0 开始,都是整数,并且之间没有间隙),则此函数返回 true。对于空数组,它也返回 true。

<?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']);
/**
* Returns false
*/
array_is_list([1 => 'rock', 2 => 'scissor']);

fsync() 和 fdatasync() 函数

PHP 8.1 添加了对 fsync() 和 fdatasync() 函数的支持。两者都与现有 fflush() 函数有相似之处,该函数当前用于将缓冲区刷新到操作系统中。
然而,fsync() 和 fdatasync() 刷新该缓冲区到物理存储。它们之间的唯一区别是该 fsync() 函数在同步文件更改时包含元数据,而该 fdatasync() 函数不包含元数据。
fsync() 函数将采用文件指针并尝试将更改提交到磁盘。成功时返回 true,失败时返回 false,如果资源不是文件,则会发出警告。fdatasync() 函数的工作方式相同,但速度稍快一些,因为 fsync () 将尝试完全同步文件的数据更改和有关文件的元数据(上次修改时间等),这在技术上是两次磁盘写入。

<?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);

数组解包

PHP 8.1 添加了对字符串键数组解包的支持。为了解压数组,PHP 使用展开 (…) 运算符。PHP 7.4 中引入了这个运算符来合并两个或多个数组,但语法更简洁。但在 PHP 8.1 之前,展开运算符仅支持带数字键的数组。请参阅以下代码片以了解如何将展开运算符用于字符串键控数组。

<?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);

IntlDatePatternGenerator 类

PHP 8.1 添加了对新 IntlDatePatternGenerator 类的支持。在 PHP 8.1 之前,只能使用 IntlDateFormatter 。虽然它支持昨天、今天和明天使用的八种预定义格式,但是这些格式和 IntlDatePatternGenerator 不太一样。
这个类允许指定日期、月份和时间的格式,并且顺序将由类自动处理。请参阅以下代码片段以了解如何使用 IntlDatePatternGenerator 类。

<?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";

纯交集类型

PHP 8.1添加了对交集类型的支持。它类似于PHP 8.0 中引入的联合类型,但它们的预期用途恰恰相反。
为了更好地理解它的用法,让我们回顾一下PHP中类型声明的工作原理。
本质上,您可以向函数参数、返回值和类属性添加类型声明。这种分配称为类型提示,并确保值在调用时是正确的类型。否则,它会立即抛出一个TypeError。反过来,这可以帮助您更好地调试代码。
但是,声明单一类型有其局限性。联合类型通过允许您声明具有多种类型的值来帮助您克服这个问题,并且输入必须至少满足声明的类型之一。
请注意使用&(AND) 运算符来声明交集类型。相反,我们使用|(OR) 运算符来声明联合类型。
在交集类型中使用大多数标准类型将导致永远无法满足的类型(例如整数和字符串)。因此,交集类型只能包括类类型(即接口和类名)。

<?php
class A {
    private Traversable&Countable $countableIterator;
    public function setIterator(Traversable&Countable $countableIterator): void {
        $this->countableIterator = $countableIterator;
    }

    /**
     * 交集类型
     * @return Countable&Traversable
     */
    public function getIterator(): Traversable&Countable {
        return $this->countableIterator;
    }

    /**
     * 联合类型
     * @return int|float
     */
    public function getIteratorTow(): int|float {
        return "one";
    }
}

使用继承缓存提高性能

继承缓存(Inheritance Cache )是opcache的新增功能,可消除PHP类继承开销。
PHP类由opcache单独编译和缓存。但是,它们已经在运行时针对每个请求进行了链接。这个过程可能涉及几个兼容性检查和从父类和特征借用方法/属性/常量。
因此,即使每个请求的结果都相同,这仍需要相当长的时间来执行。
继承缓存链接所有唯一的依赖类(父类、接口、特征、属性类型、方法)并将结果存储在opcache共享内存中。由于这种情况现在只发生一次,因此继承需要较少的指令。
此外,它消除了对不可变类的限制,例如未解析的常量、类型化属性和协变类型检查。因此,存储在opcache中的所有类都是不可变的,进一步减少了所需的指令数量。

First-Class可调用语法

PHP 8.1添加了First-Class可调用语法来取代使用字符串和数组的现有编码。除了创建更干净的Closure 之外,静态分析工具也可以访问这种新语法并尊重声明的范围。

php8.1之前版本

<?php
$closure = Closure::fromCallable('array_merge');
print_r($closure([1,2], [3,4]));
// Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )

php8.1版本

<?php
$closure = array_merge(...);
print_r($closure([1,2], [3,4]));
// Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇