PHP 8.2 有哪些新東西
PHP 8.2 在 2022/12/8 發布了,來看看有什麼新東西吧。
- Readonly Classes
- Deprecate dynamic properties
- New Rand Extension
- null, true and false as stanalone types
- Disjunctive Normal Form Types
- Constant in Trait
- Rdact parameters in back traces
- Fetch properties of enums in const expressions
- Return type changes for Date::createFormImmutable() and DateTime::createFormImmutable()
- utf8_encode() and utf8_decode() deprecations
- Locale-insensitive strtolower() and strtoupper()
- Signature chanages to serval SPL methods
- New n modifier in PCRE
- Deprecate ${} string interpolation
- New Functions and Clases
Readonly Classes
PHP 8.1 時加入了物件唯讀屬性的方法,如果要全部屬性都是唯讀,在PHP 8.2可以直接在物件開頭宣告即可
PHP 8.1
class Post
{
public function __construct(
public string $string,
public User|null $user,
public string $body,
public DateTimeInterface $publishedAt
)
{
}
}
PHP 8.2
readonly public function __construct(
public string $string,
public User|null $user,
public string $body,
public DateTimeInterface $publishedAt
)
{
}
』
Note: 如果你想擴展唯讀的物件,那子物件裡的屬性也一樣是唯讀。
Deprecate dynamic properties
Dynamic Properties 在 8.2 棄用,只有在錯誤訊息設定打開 E_DEPRECATE 的設定才會出現,在 9.0 時則會直接噴錯(Throw ErrorException)。
class Post
{
public string $title;
}
// …
$post->name = 'Name';
如果有用 get 及 set 在物件裡,就可以正常運行
class Post
{
private array $properties = [];
public function __set(string $name, mixed $value): void
{
$this->properties[$name] = $value;
}
public function __get(string $name)
{
return $this->properties[$name];
}
}
// …
$post->name = 'Name';
也可以在物件前宣告 #[AllowDynamicProperties], 就可以和之前一樣用 Dynamic Properties 了
#[AllowDynamicProperties]
class User
{
public function __construct(
readonly public string $name,
public bool $valid = true,
public string|null $password = null,
public Status $status = Status::ONLINE
)
{
}
}
New Random Extension
新的亂數擴展應用
$rng = $is_production
? new RandomEngineSecure()
: new RandomEngineMt19937();
$randomizer = new RandomRandomizer($rng);
$randomizer->shuffleArray(['abc', 'def', 'xyz']);
null, true and false as stanalone types
null, true 及 false 可以做為獨立的型態來宣告。 之前 true 及 false 要用 Boolean 的型態來宣告,null 則是在 8.0 後一定要包含在 unino 中一起宣告才行,在 php8.2 之後都可以有其獨立的型態。
php8.1
public function post(): Post|null
{
if (!empty($post)) {
return $post;
} else {
return null;
}
}
public function alwaysTrue(): Boolean
{
return true;
}
php8.2
public function alwaysTrue(): true
{
return true;
}
public function alwaysNull(): null
{
return null;
}
Disjunctive Normal Form Types 析取範式型態(DNF Type)
DNF types 可以讓我們組合聯集及交集的型態,當組合這兩個型態時,交集模型必須被括號包起來。
function generateSlug((HasTitle&HasId)|null $post)
{
if ($post === null) {
return '';
}
return
strtolower($post->getTitle())
. $post->getId();
}
在這個範例中,(HasTitle&HasId)|null 就是 DNF Type
Constant in Trait
可以在 trait 裡宣告常數了
trait HasUser
{
public const NO_USER = 0;
public const USER_INVALID = -1;
public const USER_VALID = 1;
public function checkUser()
{
if (empty($this->user)) {
throw new Exception('No User', self::NO_USER);
} else {
return $this->user;
}
}
}
可以直接用物件來呼叫常數
class Post
{
use HasUser;
...
}
Post::USER_VALID;
Rdact parameters in back traces
回追蹤跡裡的密文參數
當我們在處理錯誤時,我們會追蹤所有參數及程序堆棧,有時會發送到第三方服務。但有些時候,一些比較敏感的參數我們不希望也一起送過去,例如密碼及其他服務的帳密。 PHP 8.2可以使用屬性標記這類的敏感參數,這樣就不用擔心會把這類訊息傳送到第三方了。
以上情形適用 php.ini 有以下設定時,通常已發行的產品版本這兩個值會是 On 及 0,也就是不回傳送錯誤發生時傳送的參數過去。
zend.exception_ignore_args = Off
end.exception_string_param_max_len = 15
static public function login(User $user, string $name, #[SensitiveParameter] string $password)
{
if ($name == $user->name && $password == $user->password) {
print 'Login ok';
} else {
throw new Exception('Login fail');
}
}
User::login($user,'Tsai Yi hua', 'abcc');
傳送回來的錯誤訊息時,password 變成了 Object(SensitiveParameterValue)
Fatal error: Uncaught Exception: Login fail in /data/tyh/projects/php8.2/pratice/app/User.php:20
Stack trace:
#0 /data/tyh/projects/php8.2/pratice/test.php(27): AppUser::login(Object(AppUser), 'Tsai Yi hua', Object(SensitiveParameterValue))
#1 {main}
thrown in /data/tyh/projects/php8.2/pratice/app/User.php on line 20
Fetch properties of enums in const expressions
常數設定時,允許直接提取列舉型態中的參數
Enums/Status.php
enum Status: string
{
case ONLINE = 'online';
case OFFLINE = 'offline';
}
Post.php
class Post
{
public const ONLINE = Status::ONLINE->name;
public const OFFLINE = Status::OFFLINE?->name;
}
Return type changes for Date::createFormImmutable() and DateTime::createFormImmutable()
Date::createFormImmutable() 及 DateTime::createFormImmutable() 的回傳型態變更
Before
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
In PHP 8.2
DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): static
utf8_encode() and utf8_decode() deprecations
uft8_encdoe(), utf8_decode 在 PHP 8.2 棄用。 改用 mb_convert_encoding()
Locale-insensitive strtolower() and strtoupper()
strtolower() 及 strtoupper 拿掉對語言環境敏感的設定,也就是之後的大小寫轉換將和語言環境無關。 如果想要本地化的轉換,用 mb_strtolower 來替代。
Signature chanages to serval SPL methods
SplFileInfo::_bad_state_ex()
SplFileObject::getCsvControl()
SplFileObject::fflush()
SplFileObject::ftell()
SplFileObject::fgetc()
SplFileObject::fpassthru()
SplFileObject::hasChildren()
SplFileObject::getChildren()
New n modifier in PCRE
PCRE: Perl-compitable Regular Expression
n = NO Auto Capture
preg_match('/^(.*)@(.*)/', 'abc@aabb.cc.dd', $match);
var_dump($match);
Output
array(3) {
[0]=>
string(14) "abc@aabb.cc.dd"
[1]=>
string(3) "abc"
[2]=>
string(10) "aabb.cc.dd"
}
加上 n 後
preg_match('/^(.*)@(.*)/n', 'abc@aabb.cc.dd', $match);
var_dump($match);
Output
array(1) {
[0]=>
string(14) "abc@aabb.cc.dd"
}
這個好處是在只想比較字串是否符合 PCRE 就好,不用額外輸出比對出來的結果,較省計算資源。
Deprecate ${} string interpolation
${} 的變數取用方法棄用
"Hello ${world}";
Deprecated: Using ${} in strings is deprecated
"Hello ${(world)}";
Deprecated: Using ${} (variable variables) in strings is deprecated
New Functions and Classes
- ini_parse_quantity
- 解析PHP INI可辨識的數值。返回值為以 bytes 為單位的值。
ini_parse_quantity('1M'); // 1048576
當無法辨識時會列印出 warning 訊息,但還是傳回數值。
ini_parse_quantity('232Kg');
output
Warning: Invalid quantity "232Kg", interpreting as "232g" for backwards compatibility in /data/tyh/projects/php8.2/pratice/test.php on line 35 249108103168PHP Warning: Invalid quantity "232Kg", interpreting as "232g" for backwards compatibility in /data/tyh/projects/php8.2/pratice/test.php on line 35
- 解析PHP INI可辨識的數值。返回值為以 bytes 為單位的值。
- curl_upkeep
- 當你使用 curl 有 keep-alive 需求時,可以用這個 function
$handle = curl_init(); curl_upkeep($handle); ...
這個函式只有在 libcurl 是 7.62 以後才有用。還有連線目標如果有強制 keep-alive 時間的話,超過也無效。
- 當你使用 curl 有 keep-alive 需求時,可以用這個 function
-
openssl_cipher_key_length
-
傳回 openssl 各種編碼方式所需的秘鑰長度(bytes)
openssl_cipher_key_length("AES-128-GCM"); // 16 openssl_cipher_key_length("AES-256-GCM"); // 32
當編碼演算法不存在時則列印出 warning 訊息,並傳回 false
openssl_cipher_key_length("NO-CHIPER-ALGORITHM");
output
Warning: openssl_cipher_key_length(): Unknown cipher algorithm in /data/tyh/projects/php8.2/pratice/test.php on line 35
-