PHP 70 新特性
https://www.php.net/manual/zh/migration70.new-features.php
https://www.php.net/manual/en/migration70.new-features.php
標量類型聲明擴充
類型聲明(類型提示)在原先支持“類名,接口,數組和回調類型”的基礎上新增:
1、字符串(string); 2、整數 (int); 3、浮點數 (float); 4、以及布爾值 (bool)
返回值類型聲明
增加了對返回類型聲明的支持
null合並運算符
添加了null合並運算符 (??) 這個語法糖
$username = $_GET['user'] ?? 'nobody'; 等效 $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
太空船操作符(組合比較符)
太空船操作符用於比較兩個表達式。當$a小於、等於或大於$b時它分別返回-1、0或1。
<?php // 整數 echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // 浮點數 echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // 字符串 比如:strcmp($str1, $str2) 就可以使用以下方式簡寫 echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1
通過 define() 定義常量數組
define('ANIMALS', ['dog', 'cat', 'bird']);
匿名類
支持通過new class 來實例化一個匿名類,用來替代一些“用后即焚”的完整類定義
interface A { public function log(string $msg); } class B { } // 實例化匿名類 var_dump(new class implements A { public function log(string $msg){} }); var_dump(new class extends B{ });
Unicode codepoint 轉譯語法
接受一個以16進制形式的 Unicode codepoint,並用一個雙引號或heredoc包圍的 UTF-8 編碼格式的字符串。 可以接受任何有效的 codepoint,並且開頭的 0 是可以省略的
echo "\u{aa}"; // Output: a echo "\u{0000aa}"; // Output: a echo "\u{9999}"; // Output: 香 echo <<<EOF \u{9999} EOF; // Output: 香
Closure::call()
性能優化
為unserialize()提供過濾
旨在提供更安全的方式解包不可靠的數據。它通過白名單的方式來防止潛在的代碼注入
// 將所有的對象都轉換為 __PHP_Incomplete_Class 對象 $data = unserialize($foo, ["allowed_classes" => false]); // 將除 MyClass 和 MyClass2 之外的所有對象都轉換為 __PHP_Incomplete_Class 對象 $data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]); // 默認情況下所有的類都是可接受的,等同於省略第二個參數 $data = unserialize($foo, ["allowed_classes" => true]);
IntlChar
新增加的 IntlChar 類旨在暴露出更多的 ICU 功能。這個類自身定義了許多靜態方法用於操作多字符集的 unicode 字符。
printf('%x', IntlChar::CODEPOINT_MAX); // Output: 10ffff echo IntlChar::charName('@'); // Output: COMMERCIAL AT var_dump(IntlChar::ispunct('!')); // Output: bool(true) // 若要使用此類,請先安裝Intl擴展
預期
預期是向后兼用並增強之前的 assert() 的方法。 它使得在生產環境中啟用斷言為零成本,並且提供當斷言失敗時拋出特定異常的能力。
老版本的API出於兼容目的將繼續被維護,assert()現在是一個語言結構,它允許第一個參數是一個表達式,而不僅僅是一個待計算的 string或一個待測試的boolean。
ini_set('assert.exception', 1); class CustomError extends AssertionError {} assert(false, new CustomError('Some error message')); // Output:"Fatal error: Uncaught CustomError: Some error message"
PHP測試框架如:phpunit 中很常見
Group use declarations
從同一 namespace 導入的類、函數和常量現在可以通過單個 use 語句 一次性導入了。
// PHP 7 之前的代碼 use some\namespace\ClassA; use some\namespace\ClassB; use some\namespace\ClassC as C; use function some\namespace\fn_a; use function some\namespace\fn_b; use function some\namespace\fn_c; use const some\namespace\ConstA; use const some\namespace\ConstB; use const some\namespace\ConstC; // PHP 7+ 及更高版本的代碼 use some\namespace\{ClassA, ClassB, ClassC as C}; // 該示例在實際面向對象開發中可以也應該經常被套用 use function some\namespace\{fn_a, fn_b, fn_c}; use const some\namespace\{ConstA, ConstB, ConstC};
生成器可以返回表達式
此特性基於 PHP 5.5 版本中引入的生成器特性構建,它允許在生成器函數中通過使用 return 語法來返回一個表達式 (但是不允許返回引用值), 可以使用新方法 Generator::getReturn() 獲取返回值,但該方法只能在生成器完成yielding values之后使用。
$gen = (function() { yield 1; yield 2; return 99; })(); // echo $gen->getReturn(); 致命錯誤,因為Generator::getReturn()方法只能在生成器完成yielding values之后使用 foreach ($gen as $val) { // 生成器被迭代(yielding value)兩次 echo $val, PHP_EOL; } echo $gen->getReturn(), PHP_EOL; //Output:
1
2
99
生成器委派
現在,只需在最外層生成器中使用 yield from,就可以把一個生成器自動委派給其他的生成器,Traversable 對象或 array
function gen() { yield 1; yield 2; yield from gen2(); }
function gen2() { yield 3; yield 4; } foreach (gen() as $val) { echo $val, PHP_EOL; } // Output:
1
2
3
4
整數除法函數 intdiv()
新加函數 intdiv() 用來進行整數的除法運算。
var_dump(intdiv(10, 3)); // Output: 3 其結果相當於 intval(10 / 3) Or (int)(10 / 3),但是性能肯定是intdiv更好
Session會話選項
session_start()可以接受一個 array 作為參數, 用來覆蓋 php.ini 文件中設置的 會話配置選項。
These options have also been expanded to support session.lazy_write, which is on by default and causes PHP to only overwrite any session file if the session data has changed, and read_and_close, which is an option that can only be passed to session_start() to indicate that the session data should be read and then the session should immediately be closed unchanged.
session_start([ 'cache_limiter' => 'private', // session在客戶端的緩存方式,有nocache,private,private_no_expire,public;私有方式緩存 - private(比如:表單信息被保留,但在生存期內有效) 'read_and_close' => true, // 如果會話數據沒有發生改變,那么 PHP 會在讀取完session之后,立即關閉會話存儲文件 ]);
preg_replace_callback_array()優化
在 PHP 7 之前,當使用 preg_replace_callback() 函數的時候, 由於針對每個正則表達式都要執行回調函數,可能導致過多的分支代碼。 而使用新加的 preg_replace_callback_array() 函數, 可以使得代碼更加簡潔。
現在,可以使用一個關聯數組來對每個正則表達式注冊回調函數, 正則表達式本身作為關聯數組的鍵, 而對應的回調函數就是關聯數組的值。
新增兩個跨平台的隨機函數
random_bytes() 用來產生高安全級別的隨機字符串
random_int() 用來產生高安全級別的隨機整數。 更早版本時只能使用相對較安全的過渡函數 mt_rand(),rand()就更不用說了。
list() 函數bug修復
在之前版本中,list() 不能保證正確展開實現了 ArrayAccess 接口的對象, 現在這個問題已修復。(list 不是真正的函數,而是語言結構)
其他特性
允許在克隆表達式上訪問對象成員,例如: (clone $foo)->bar()。 不需要 $newFoo = clone $foo; $newFoo->bar();分開兩句來寫
PHP 71 新特性
https://www.php.net/manual/zh/migration71.new-features.php
https://www.php.net/manual/en/migration71.new-features.php
可為空(Nullable)類型
參數以及返回值的類型可以通過在類型前加上一個問號使之允許為空。
function testReturn(): ?string // 限定函數只能返回string or null { }
Void 函數
一個新的返回值類型void被引入。 返回值類型聲明為 void 的方法要么沒有 return 語句,要么 return 直接接分號 。(return null;不合法; return ;合法)
Symmetric array destructuring 對稱數組分解
短數組語法([])現在作為list()語法的一個備選項,可以用於將數組的值賦給一些變量(包括在foreach中),且支持鍵名。
$data = [ ["id" => 1, "name" => 'Tom'], ["id" => 2, "name" => 'Fred'], ]; // 等效,支持鍵名 list("id" => $id1, "name" => $name1) = $data[0]; ["id" => $id1, "name" => $name1] = $data[0]; // 等效,支持鍵名 foreach ($data as list("id" => $id, "name" => $name)) { // logic here with $id and $name } foreach ($data as ["id" => $id, "name" => $name]) { // logic here with $id and $name }
類常量可見性
現在起支持設置類常量的可見性。
class ConstDemo { const PUBLIC_CONST_A = 1; public const PUBLIC_CONST_B = 2; // 關鍵字const之前可以指定 public、potected等 protected const PROTECTED_CONST = 3; private const PRIVATE_CONST = 4; }
引入iterable 偽類
引入了一個新的被稱為 iterable 的偽類 (與callable類似)。 這可以被用在參數或者返回值類型中,它代表接受數組或者實現了Traversable接口的對象。 對於子類,當用作參數時子類的參數類型可以將父類的 array 或 Traversable 聲明拓展到 iterable;對於返回值類型,子類可以將父類的返回類型 iterable 收緊到 array 或 實現 Traversable 的對象。
class A { function iterator(Traversable $iter): iterable { foreach ($iter as $val) { // } } } // 合法的重寫,編譯通過 class B extends A { /** * @param iterable $iter 拓展參數類型 Traversable 到 iterable * @return array 收緊返回值類型 iterable 到 array */ function iterator(iterable $iter): array { foreach ($iter as $val) { // } } }
多異常捕獲處理
一個catch語句塊現在可以通過管道字符(|)來實現多個異常的捕獲。 這對於需要同時處理來自不同類的不同異常時很有用。
try { // some code } catch (FirstException | SecondException $e) { // handle first and second exceptions }
支持為負的字符串偏移量
現在所有支持偏移量的字符串操作函數 都支持接受負數作為偏移量,包括通過[]或{}操作字符串下標。在這種情況下,一個負數的偏移量會被理解為一個從字符串結尾開始的偏移量。
var_dump("abcdef"[-2]); // Output: string (1) "e" var_dump(strpos("aabbcc", "b", -3)); // Output: int(3) $string = 'bar'; echo "The last character of '$string' is '$string[-1]'.\n"; // Output: The last character of 'bar' is 'r'.
ext/openssl 支持 AEAD模式
Support for AEAD (modes GCM and CCM) have been added by extending the openssl_encrypt() and openssl_decrypt() functions with additional parameters.
通過 Closure::fromCallable() 將callable轉為閉包
Closure新增了一個靜態方法,用於將callable快速轉換為一個Closure 對象。
class Test { /** * @return Closure * @internal 該函數把私有方法 privateFunction 暴露給了開發者 */ public function exposeFunction() { return Closure::fromCallable([$this, 'privateFunction']); } private function privateFunction($param) { var_dump($param); } } $closure = (new Test)->exposeFunction(); $closure('some value'); // Output: string(10) "some value"
異步信號處理(參見declare)
一個新的名為 pcntl_async_signals() 的方法現在被引入, 用於啟用無需 ticks (這會帶來很多額外的開銷)的異步信號處理。
pcntl_async_signals(true); // turn on async signals pcntl_signal(SIGHUP, function($sig) { echo "SIGHUP\n"; }); posix_kill(posix_getpid(), SIGHUP); // Output: SIGHUP
具體作用參考: https://www.gaojiufeng.cn/?id=238
HTTP/2 server push support in ext/curl
CURL擴展中增加了對服務器推送的支持(需要libcurl7.46及更高版本)。這可以通過 curl_multi_setopt() 函數和為常量 CURLMOPT_PUSHFUNCTION 選項設定一個推送回調(pushCallback)來激活該功能。
PHP71還新增了常量 CURL_PUSH_OK 和 CURL_PUSH_DENY ,用以表示批准或拒絕執行服務器推送的回調
Stream Context Options
The tcp_nodelay stream context option has been added. 新增一個流上下文選項:tcp_nodelay
// connect to the internet using the '192.168.0.100' IP and port '7000' $opts = array( 'socket' => array( 'bindto' => '192.168.0.100:7000', ), 'tcp_nodelay' => true, // set SOL_TCP,NO_DELAY=1 appropriately, thus disabling the TCP Nagle algorithm. 設置SOL_TCP,NO_DELAY=1,從而禁用TCP Nagle算法 ); // create the context... $context = stream_context_create($opts); // ...and use it to fetch the data echo file_get_contents('http://www.example.com', false, $context);
PHP 72 新特性
https://www.php.net/manual/zh/migration72.new-features.php
https://www.php.net/manual/en/migration72.new-features.php
新的對象類型
這種新的對象類型, object, 引進了可用於逆變(contravariant)參數輸入和協變(covariant)返回任何對象類型。
function test(object $obj) : object { return new SplQueue(); } test(new StdClass());
通過名稱加載擴展
加載擴展時不再需要指定文件擴展名 (Unix下以.so為文件擴展名,在Windows下以 .dll 為文件擴展名) 。
比如:extension=mysqli 就可以了,而不用 extension=mysqli.so
允許重寫抽象方法(Abstract method)
abstract class A { abstract function test(string $s); } abstract class B extends A { // overridden - still maintaining contravariance for parameters and covariance for return abstract function test($s) : int; }
使用Argon2算法生成密碼散列
Argon2 已經被加入到密碼散列(password hashing) API (這些函數以 password_ 開頭), 以下是暴露出來的常量:
PASSWORD_ARGON2I
PASSWORD_ARGON2_DEFAULT_MEMORY_COST
PASSWORD_ARGON2_DEFAULT_TIME_COST
PASSWORD_ARGON2_DEFAULT_THREADS
新增 ext/PDO(PDO擴展) 字符串擴展類型
當你准備支持多語言字符集,PDO的字符串類型已經擴展支持國際化的字符集。以下是擴展的常量
PDO::PARAM_STR_NATL
PDO::PARAM_STR_CHAR
PDO::ATTR_DEFAULT_STR_PARAM
$db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL); //這些常量通過 PDO::PARAM_STR 利用位運算OR進行計算
為 ext/PDO擴展新增額外的模擬調試信息
PDOStatement::debugDumpParams()方法已經更新,當發送SQL到數據庫的時候,在一致性、行查詢(包括替換綁定占位符)將會顯示調試信息。這一特性已經加入到模擬調試中(在模擬准備打開時可用)。
ext/LDAP(LDAP擴展) 支持新的操作方式
LDAP 擴展已經新增了EXOP支持. 擴展暴露以下函數和常量:
- ldap_parse_exop()
- ldap_exop()
- ldap_exop_passwd()
- ldap_exop_whoami()
LDAP_EXOP_START_TLS
LDAP_EXOP_MODIFY_PASSWD
LDAP_EXOP_REFRESH
LDAP_EXOP_WHO_AM_I
LDAP_EXOP_TURN
ext/sockets(sockets擴展)添加了地址信息
sockets擴展現在具有查找地址信息的能力,且可以連接到這個地址,或者進行綁定和解析。為此添加了以下一些函數:
Parameter type widening
放寬參數類型限制:重寫方法和接口實現的參數類型可以省略。不過這仍然是符合LSP,因為現在這種參數類型是逆變的。
interface A { public function Test(array $input); } class B implements A { public function Test($input){} // type omitted for $input }
允許使用逗號批量引入同一命名空間下的 trait 類
PHP 7中命名空間允許使用逗號進行分組引入。
use Foo\Bar\{
Foo,
Bar,
Baz,
};
其他特性
- Windows下也支持 proc_nice() 函數
- pack() 和 unpack() endian支持
- 增強EXIF、ZIP擴展
- SQLite3 allows writing BLOBs
- ...
因為平時基本不會接觸,所以具體參考英文文檔吧
PHP 73 新特性
https://www.php.net/manual/zh/migration73.new-features.php
https://www.php.net/manual/en/migration73.new-features.php
更加靈活的Heredoc和Nowdoc語法
文檔字符串的結束標記后面不再需要緊跟分號(;)或換行。另外,結束標記可以縮進,在這種情況下,縮進將從doc字符串中的每一行中刪除。(可以使用空格或tab縮進,但是doc字符串和結束標記必須使用相同的縮進方式,要么都使用空格,要么都是tab,否則報錯)
<?php echo <<<'NOW' 123 456 789
NOW // 此處可以省略分號,因為緊跟PHP結束標記 ?> // Output: (注意縮進:因為結束標記縮進了,所以doc字符串的每一行都刪除相同的縮進)
123
456
789
<?php $nowDoc = <<<'NOW' 123 456 789 NOW ; echo "ASD\n" . $nowDoc;
// Output:(注意縮進)
ASD
123
456
789
對稱數組分解支持引用賦值
數組分解([])現在支持引用賦值,list() 也一樣。
$d = ['I am A', ['bbb', 'I am C']]; [&$a, [$b, &$c]] = $d; // 變量$a, $c 是引用賦值 // [&$a, [$b, &$c]] = ['I am A', ['bbb', 'I am C']]; 引用錯誤,編譯不通過
Instanceof運算符接受字面量(Liters)
instanceof 現在允許字面量作為第一個操作數,在這種情況下,結果總是 FALSE。
PS:什么是字面量?
Value代表具體值,Literals則代表如何表達這個值。譬如說,15這是一個值,這個值是唯一的,但表達的方式有很多種:例如用阿拉伯數字寫出來:15,用中文寫出來:十五,用英文表達:fifteen,用16進制:0xF。15是value,后面的種種都是literal。
class A { } // 7.3之前前兩個 var_dump 會編譯錯誤 var_dump(A::class instanceof A); // Output: false var_dump('A' instanceof A); // Output: false var_dump(new A instanceof A); // Output: true
// 除了增強了 instanceof 容錯性,暫時是沒發現其他好處
異常類 CompileError 代替某些編譯錯誤
A new CompileError exception has been added, from which ParseError inherits. A small number of compilation errors will now throw a CompileError instead of generating a fatal error. Currently this only affects compilation errors that may be thrown by token_get_all() in TOKEN_PARSE
mode, but more errors may be converted in the future. 底層新增的一個 CompileError 異常類。少量編譯錯誤的情況現在將引發CompileError,而不是拋出致命錯誤。目前,這只會影響在TOKEN_PARSE模式下
token_get_all(),將來可能會轉換更多錯誤。
Trailing Commas are allowed in Calls
允許調用方法、函數時使用逗號尾隨。 官方文檔中有人給出了這樣的示例
// "Trailing commas in function and method calls are now allowed" means function parameters 尾隨逗號,是針對函數或方法的參數而言的 function my1() { echo "xxxxxx\n"; } function my2() { echo "yyyyyy\n"; } my1(),my2(); // PHP Parse error: syntax error my1(,); // PHP Parse error: syntax error my1(1,); my2(2,); // OK
Argon2id 支持
The --with-password-argon2[=dir] configure argument now provides support for both Argon2i and Argon2id hashes in the password_hash(), password_verify(), password_get_info(), and password_needs_rehash() functions. Passwords may be hashed and verified using the PASSWORD_ARGON2ID
constant. Support for both Argon2i and Argon2id in the password_*() functions now requires PHP be linked against libargon2 reference library ≥ 20161029. 大體就是新增了Argon2id哈希算法支持
FastCGI Process Manager(FPM)
添加了新選項以自定義FPM日志:
log_limit
此全局選項可用於設置日志行的日志限制,允許記錄長度超過1024個字符的消息而不進行換行。它還修復了各種換行問題。
log_buffering
This global option allows an experimental logging without extra buffering. 此全局選項允許不借助其它緩沖的情況下進行experimental logging。
decorate_workers_output
This pool option allows to disable the output decoration for workers output when catch_workers_output is enabled.
BC Math 數學運算函數
bcscale() 現在也可以用作getter來檢索當前使用的scale(之前只能設置不能檢索,返回值是bool;現在既能設置又能檢索,返回值是int)
bcscale(2) ; // 設置所有bc數學函數的默認小數點保留2位小數 echo bcscale(); // 獲取所有bc數學函數的默認小數點保留位數 Output: 2
Lightweight Directory Access Protocol
Full support for LDAP Controls has been added to the LDAP querying functions and ldap_parse_result():
- A $serverctrls parameter to send controls to the server in ldap_add(), ldap_mod_replace(), ldap_mod_add(), ldap_mod_del(), ldap_rename(), ldap_compare(), ldap_delete(), ldap_modify_batch(), ldap_search(), ldap_list() and ldap_read() has been added.
- The out parameter $serverctrls to get controls from the server in ldap_parse_result() has been added.
- Support for
LDAP_OPT_SERVER_CONTROLS
andLDAP_OPT_CLIENT_CONTROLS
in ldap_get_option() and ldap_set_option() has been fixed.
Multibyte String Functions 多字節字符串函數
mbstring擴展庫的一些函數得到增強,優化。
- 增加對 full case-mapping 和 full case-folding 的支持,與 simple case-mapping 不同,full case-mapping可能會更改字符串的長度。
mb_strtoupper("Straße"); // Produces STRAßE on PHP 7.2 // Produces STRASSE on PHP 7.3
MB_CASE_LOWER
(used by mb_strtolower())MB_CASE_UPPER
(used by mb_strtoupper())MB_CASE_TITLE
MB_CASE_FOLD
MB_CASE_LOWER_SIMPLE
MB_CASE_UPPER_SIMPLE
MB_CASE_TITLE_SIMPLE
MB_CASE_FOLD_SIMPLE
(used by case-insensitive operations)
- 不區分大小寫的字符串操作,現在比較時使用 case-folding 而不是 case-mapping。這意味着現在有更多的字符將被當成是相同的(大小寫不敏感)。
- 使用 MB_CASE_TITLE 進行 mb_convert_case() 時,會基於大小寫和大小寫可忽略的派生Unicode屬性執行 title-case(標題大小寫)轉換。特別是,這還改進了引號和撇號的處理。
- The Multibyte String data tables have been updated for Unicode 11.
- 現支持正確處理大於2GB的字符串。
- 性能改進提升,最大的改進是大小寫轉換函數。
- mb_ereg_x*函數現在支持命名捕獲。匹配函數,如:mb_ereg() 現在將使用組號和組名返回命名捕獲,類似於PCRE:
mb_ereg('(?<word>\w+)', '國', $matches); // Output: [0 => "國", 1 => "國", "word" => "國"]; // 另外, 在字符串替換時 mb_ereg_replace() 現支持用 \k<> and \k'' 符號來引用命名捕獲: mb_ereg_replace('\s*(?<word>\w+)\s*', "_\k<word>_\k'word'_", ' foo '); // Output: "_foo_foo_"
\k<> and \k'' can also be used for numbered references, which also works with group numbers greater than 9. 【\k<>和\k''也可用於編號引用,這也適用於組號大於9的情況?】
Readline
readline_info() 中添加了對 completion_append_character 和 completion_suppress_append 選項的支持。只有當PHP鏈接到libreadline(而不是libedit)時,這些選項才可用。
PHP 74 新特性
https://www.php.net/manual/zh/migration74.new-features.php
https://www.php.net/manual/en/migration74.new-features.php
類型化屬性
類屬性支持類型聲明
class User { public int $id; // 限定該屬性只能被賦予 int 類型的值 public string $name; // 限定該屬性只能被賦予 string 類型的值 }
Arrow functions 箭頭函數/短閉包
剪頭函數提供了一種簡捷語法,用於定義具有隱式按值范圍綁定的函數。
$factor = 10; $nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]); // $nums = array(10, 20, 30, 40); /** 如果要通過引用返回值,可以使用以下語法: */ fn&($n) => $n
注意事項:
- 可以訪問父作用域,不需要 use 關鍵字。
- $this 可以像普通的閉包一樣使用。
- 短閉包只能包含一行,也就是 return 語句,但是不需要也不能有 return 關鍵字(隱式返回)。
返回類型變異(協方差)、參數類型逆變
class A {} class B extends A {} class Producer { public function covariance(): A {} public function contravariance(B $b) {} } class ChildProducer extends Producer { public function covariance(): B {} public function contravariance(A $a) {} }
Null 合並運算符
$data['date'] = $data['date'] ?? new DateTime(); $data['date'] ??= new DateTime(); // PHP74中支持更簡潔的寫法
數組內展開運算符
$arrayA = [1, 2, 3]; $arrayB = [4, 5]; $result = [0, ...$arrayA, ...$arrayB, 6 ,7]; // 變量值:$result = [0, 1, 2, 3, 4, 5, 6, 7]
注意:這僅適用於“數字下標”的數組。
數字字面量分隔符
數字字面量在兩個數字之間使用下划線"_"分割。
6.674_083e-11; // float 299_792_458; // decimal 0xCAFE_F00D; // hexadecimal 0b0101_1111; // binary
弱引用
弱引用允許程序員保留對某個對象的引用,但該引用不會阻止對象被銷毀。
允許異常來至 __toString() 方法
現在允許從 __toString() 中拋出異常,以前這會導致致命錯誤,字符串轉換中現有的可恢復致命錯誤已轉換為 Error 異常。
CURL
如果擴展是針對libcurl>=7.56.0構建的,那么除了純文件名之外,CURLFile現在還支持流包裝器。
Filter
變量過濾器 FILTER_VALIDATE_FLOAT 現在支持 min_range 和 max_range 選項, FILTER_VALIDATE_INT 也一樣。【filter_var() - 可以使用特定的過濾器過濾一個變量,FILTER_VALIDATE_FLOAT只是其中一個過濾器。】
// for filters that accept options, use this format $options = array( 'options' => array( 'default' => 3, // value to return if the filter fails // other options here 'min_range' => 0 ), 'flags' => FILTER_FLAG_ALLOW_OCTAL, ); $var = filter_var('0755', FILTER_VALIDATE_INT, $options); // for filter that only accept flags, you can pass them directly $var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); // for filter that only accept flags, you can also pass as an array $var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)); // callback validate filter function foo($value) { // Expected format: Surname, GivenNames if (strpos($value, ", ") === false) return false; list($surname, $givennames) = explode(", ", $value, 2); $empty = (empty($surname) || empty($givennames)); $notstrings = (!is_string($surname) || !is_string($givennames)); if ($empty || $notstrings) { return false; } else { return $value; } } $var = filter_var('Doe, Jane Sue', FILTER_CALLBACK, array('options' => 'foo'));
外部函數接口,簡稱 FFI
FFI是一個新的擴展,它提供了一種簡單的方式來調用本機函數、訪問本機變量以及創建/訪問在C代碼庫中定義的數據結構,即允許從用戶區調用 C 代碼。這意味着可以用純 PHP 編寫PHP擴展。應該指出,這是一個復雜的話題。您仍然需要 C 知識才能正確使用此功能
GD庫
添加了 IMG_FILTER_SCATTER 圖像過濾器,以將一個 scatter filter 應用於圖像。
哈希
使用 Castagnoli 多項式添加了 crc32c 哈希散列。此CRC32變體被用於存儲系統,如iSCSI、SCTP、Btrfs和ext4。
多字節字符串
新增 mb_str_split() 函數,該函數提供了與 str_split() 一樣的功能,但是操作的是 code points 而不是字節。
OPcache緩存預加載
預加載應該是該版本最值得一提的優化了,可以帶來很大性能改進。簡而言之:如果您今天使用的是框架,則必須在每次請求時加載和重新編譯其文件。預加載允許服務器在啟動時於內存中加載 PHP 文件,並使它們持久化用於所有后續請求(只要不停電)。
不過如果預加載文件的源文件發生變化,則必須重新啟動服務器(該部分若有異議,請查看 RFC 詳細介紹)
正則表達式(Perl兼容)
preg_replace_callback() 和 preg_replace_callback_array() 函數現在接受一個附加的flags參數,並支持 PREG_OFFSET_CAPTURE 和 PREG_UNMATCHED_AS_NULL 標志。這會影響傳遞給回調函數的匹配數組的格式。
PDO擴展
現在可以將用戶名和密碼指定為mysql、mssql、sybase、dblib、firebird和oci驅動程序的PDO DSN的一部分,以前這只受pgsql驅動程序支持。如果在構造函數和DSN中都指定了用戶名/密碼,則構造函數優先。
現在可以在SQL查詢中轉義問號,以避免它們被解釋為參數占位符,寫作 ?? 。例如使用PostgreSQL JSON 鍵 exists(?) 操作符。
- PDOStatement::getColumnMeta() 現在是可用支持的。
- PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) 允許檢查語句是否是只讀的,即它是否沒有修改數據庫。
- PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true) 允許在 PDO::errorInfo() 和 PDOStatement::errorInfo() 中使用SQLite3擴展結果代碼。
- 添加了 SQLite3::lastExtendedErrorCode() 以獲取最后一個擴展的結果代碼.
- 添加了 SQLite3::enableExtendedResultCodes($enable=true),這將使 SQLite3::lastErrorCode() 返回擴展的結果代碼。
strip_tags() 函數增強
strip_tags() 現在也支持 strip_tags($str, ['a', 'p']) 寫法,等效於原來的寫法 strip_tags($str, '<a><p>') 。
自定義對象序列化
RFC 增加了兩個新的魔術方法:__serialize 和 __unserialize 。這些方法和 __sleep 以及 __wakeup 的不同之處已經在 RFC 中進行了討論,主要是解決 __sleep, __wakeup 和 Serializable 帶來的一些問題,如:__sleep只能用於從序列化中排除屬性,但如果序列化后類的表示形式與內存中的形式有很大不同,使用起來則很麻煩。
// Returns array containing all the necessary state of the object. public function __serialize(): array; // Restores the object state from the given data array. public function __unserialize(array $data): void;
新的序列化機制將取代 Serializable 接口,后者將在將來被棄用。
不帶參數的數組合並函數
array_merge() and array_merge_recursive() 現在可以不帶任何參數進行調用,在這種情況下,它們將返回一個空數組。這與展開運算符(spread operator)結合使用非常有用,例如array_merge(…$arrays)。
proc_open() 函數
現在 proc_open() 的第一個參數接受一個數組而不是一個字符串。在這種情況下,進程將被直接打開(不經過shell),且PHP將負責任何必要的參數轉義。
proc_open(['php', '-r', 'echo "Hello World\n";'], $descriptors, $pipes);
支持 重定向 和 null 描述符
// Like 2>&1 on the shell proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes); // Like 2>/dev/null or 2>nul on the shell proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
argon2i(d) without libargon
當PHP在沒有 libargon 的情況下構建時,password_hash() 現已有了來至 sodium 擴展的 argon2i 和 argon2id 實現。
password_hash() now has the argon2i and argon2id implementations from the sodium extension when PHP is built without libargon.
PS:PHP8 最引人注目的應該是引入了JIT(Just In Time), 但是從各種文檔資料顯示:要真正盡可能的達到“變編譯邊執行”的效果,需要開發者不斷的嘗試測試。
參考:
https://51shenyun.cn/php74/ PHP7.4新特性,OPcache將支持預加載
https://www.php.cn/topic/php7/437161.html PHP 7.4中的預加載(Opcache Preloading)