<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [php4變化日志](https://www.php.net/ChangeLog-4.php)(主要是修復bug方面) [php5變化日志](http://php.net/ChangeLog-5.php)(主要是修復bug方面) [php7變化日志](http://php.net/ChangeLog-7.php)(主要是修復bug方面) [更新日志](https://www.php.net/manual/zh/doc.changelog.php)(綁定的擴展的函數更新內容) [遷移日志(包含新增或廢棄的特性和函數等)](https://www.php.net/manual/zh/appendices.php) * [**php5.4新特性**](http://www.hmoore.net/a173512/php_note/1690470#php54_7) * [**增加短數組支持如:\[1, 2, 3, 4\]**](http://www.hmoore.net/a173512/php_note/1690470#1_2_3_4_8) * [**新增Trait**](http://www.hmoore.net/a173512/php_note/1690470#Trait_9) * [**php5.5新特性**](http://www.hmoore.net/a173512/php_note/1690470#php55_10) * [**新增yield關鍵字簡化生成器**](http://www.hmoore.net/a173512/php_note/1690470#yield_11) * [**異常處理新增finally塊,`try{}catch{}finally{}`**](http://www.hmoore.net/a173512/php_note/1690470#finallytrycatchfinally_128) * [**php5.6 新特性**](http://www.hmoore.net/a173512/php_note/1690470#php56__130) * [**可變數量的參數**](http://www.hmoore.net/a173512/php_note/1690470#_131) * [**使用表達式定義常量**](http://www.hmoore.net/a173512/php_note/1690470#_169) * [**新增冪運算**](http://www.hmoore.net/a173512/php_note/1690470#_177) * [**新增\_\_debugInfo()魔術方法 當使用vardump打印類對象時觸發**](http://www.hmoore.net/a173512/php_note/1690470#__debugInfo_vardump_182) * [**擴展了use 以前可以導入命名空間的類現在還可以導入函數及常量**](http://www.hmoore.net/a173512/php_note/1690470#use__183) * [**php7新特性**](http://www.hmoore.net/a173512/php_note/1690470#php7_210) * [**1.在use語句增加了group支持**](http://www.hmoore.net/a173512/php_note/1690470#1usegroup_223) * [**2.類型約束與標量類型聲明(標量string、int、float和 bool)**](http://www.hmoore.net/a173512/php_note/1690470#2stringintfloat_bool_232) * [**3.返回值類型聲明**](http://www.hmoore.net/a173512/php_note/1690470#3_348) * [**4.三元運算新增null合并運算符??**](http://www.hmoore.net/a173512/php_note/1690470#4null_368) * [**5.太空船操作符(組合比較符)**](http://www.hmoore.net/a173512/php_note/1690470#5_374) * [**6.define支持定義數組**](http://www.hmoore.net/a173512/php_note/1690470#6define_392) * [**7.支持**](http://www.hmoore.net/a173512/php_note/1690470#7httpswwwphpnetmanualzhlanguageoop5anonymousphp_396)**[匿名類](https://www.php.net/manual/zh/language.oop5.anonymous.php)** * [](http://www.hmoore.net/a173512/php_note/1690470#8Unicodehttpswwwcnblogscomchrisoilp8677309html_424)[**8.Unicode字符編碼表**](https://www.cnblogs.com/chris-oil/p/8677309.html) * [**9.增強之前的**](http://www.hmoore.net/a173512/php_note/1690470#9asserthttpswwwphpnetmanualzhfunctionassertphp_431)**[assert()](https://www.php.net/manual/zh/function.assert.php)的方法** * [**assert.exception**](http://www.hmoore.net/a173512/php_note/1690470#assertexception_444) * [**10.為unserialize()提供過濾**](http://www.hmoore.net/a173512/php_note/1690470#10unserialize_470) * [**11.增加Closure::call支持**](http://www.hmoore.net/a173512/php_note/1690470#11Closurecall_482) * [**12.新增整數除法函數**](http://www.hmoore.net/a173512/php_note/1690470#12_529) * [**13.新增加的 IntlChar 類**](http://www.hmoore.net/a173512/php_note/1690470#13_IntlChar__538) * [**14.新增兩個跨平臺函數:**可用于生成salt、密鑰或初始化向量](http://www.hmoore.net/a173512/php_note/1690470#14_salt_554) * [**15.新增preg\_replace\_callback\_array()函數,比preg\_replace\_callback()函數簡潔**](http://www.hmoore.net/a173512/php_note/1690470#15preg_replace_callback_arraypreg_replace_callback_620) * [**16.session\_start()可以接受一個array作為參數**](http://www.hmoore.net/a173512/php_note/1690470#16session_startarray_624) * [**17.生成器中引入其他生成器**](http://www.hmoore.net/a173512/php_note/1690470#17_635) * [**18.生成器可以返回表達式**](http://www.hmoore.net/a173512/php_note/1690470#18_663) * [**php7.1新特性**](http://www.hmoore.net/a173512/php_note/1690470#php71_695) * [**參數和返回類型支持null,前提是在類型前加?**](http://www.hmoore.net/a173512/php_note/1690470#null_696) * [**php7.1返回類型新增void**](http://www.hmoore.net/a173512/php_note/1690470#php71void_727) * [**短數組語法(*\[\]*)現在作為list()語法的一個備選項,可以用于將數組的值賦給一些變量(包括在*foreach*中)**](http://www.hmoore.net/a173512/php_note/1690470#listforeach_762) * [**字符串偏移量可以為負,表示為一個從字符串結尾開始的偏移量**](http://www.hmoore.net/a173512/php_note/1690470#_809) * [**字符串負偏移在簡單的變量解析語法中也支持能了**](http://www.hmoore.net/a173512/php_note/1690470#_819) * [**對服務器推送的支持現在已經被加入到 CURL 擴展(v7.46)中**](http://www.hmoore.net/a173512/php_note/1690470#_CURL_v746_825) * [**異步信號處理**](http://www.hmoore.net/a173512/php_note/1690470#_870) * [**新增Closure::fromCallable() 將callables轉為閉包**](http://www.hmoore.net/a173512/php_note/1690470#ClosurefromCallable_callables_883) * [**php7.2新特性**](http://www.hmoore.net/a173512/php_note/1690470#php72_902) * [**新的對象類型**](http://www.hmoore.net/a173512/php_note/1690470#_903) * [**既可以通過 php.ini 也可以運行時通過 dl(string $library): bool載入一個 PHP 擴展**](http://www.hmoore.net/a173512/php_note/1690470#_phpini__dlstring_library_bool_PHP__913) * [**允許重寫抽象方法**](http://www.hmoore.net/a173512/php_note/1690470#_934) * [**重寫方法和接口實現的參數類型現在可以省略**](http://www.hmoore.net/a173512/php_note/1690470#_948) * [**php7.3新特性**](http://www.hmoore.net/a173512/php_note/1690470#php73_960) * [**更靈活的`Heredoc`和`Nowdoc`語法**](http://www.hmoore.net/a173512/php_note/1690470#HeredocNowdoc_961) * [**數組析構與list結構支持引用賦值**](http://www.hmoore.net/a173512/php_note/1690470#list_1010) * [\*\* instanceof 運算符支持字面量語法\*\*](http://www.hmoore.net/a173512/php_note/1690470#_instanceof__1017) * [**支持調用時參數的末尾跟隨逗號,但是定義是不行的**](http://www.hmoore.net/a173512/php_note/1690470#_1024) * [**BC 數學函數**](http://www.hmoore.net/a173512/php_note/1690470#BC__1032) * [**廢棄大小寫不敏感的常量**](http://www.hmoore.net/a173512/php_note/1690470#_1036) * [**命名捕獲支持**](http://www.hmoore.net/a173512/php_note/1690470#_1039) * [**php7.4新特性**](http://www.hmoore.net/a173512/php_note/1690470#php74_1060) * [**預加載**](http://www.hmoore.net/a173512/php_note/1690470#_1062) * [**類屬性現在支持類型聲明**](http://www.hmoore.net/a173512/php_note/1690470#_1068) * [**短閉包函數**](http://www.hmoore.net/a173512/php_note/1690470#_1078) * [**Null 合并運算符**](http://www.hmoore.net/a173512/php_note/1690470#Null__1122) * [**數組擴展運算符(展開運算符)**](http://www.hmoore.net/a173512/php_note/1690470#_1132) * [**自定義對象序列化**](http://www.hmoore.net/a173512/php_note/1690470#_1142) * [**數字分隔符**](http://www.hmoore.net/a173512/php_note/1690470#_1145) * [**支持反射引用**](http://www.hmoore.net/a173512/php_note/1690470#_1153) * [**改進的類型差異(協變返回和逆變參數)**](http://www.hmoore.net/a173512/php_note/1690470#_1156) * [**箭頭函數**](http://www.hmoore.net/a173512/php_note/1690470#_1179) * [**php8**](http://www.hmoore.net/a173512/php_note/1690470#php8_1212) * [**參數最后可尾隨`,`**](http://www.hmoore.net/a173512/php_note/1690470#_1213) * [不推薦在可選參數之后傳遞強制參數,但null除外](http://www.hmoore.net/a173512/php_note/1690470#null_1217) * [**新增注解功能**](http://www.hmoore.net/a173512/php_note/1690470#_1231) * [**在構造函數中聲明類的屬性**](http://www.hmoore.net/a173512/php_note/1690470#_1233) * [**新增聯合類型**](http://www.hmoore.net/a173512/php_note/1690470#_1257) * [**新增`match`表達式**](http://www.hmoore.net/a173512/php_note/1690470#match_1259) * [**新增Nullsafe 運算符(`?->`)**](http://www.hmoore.net/a173512/php_note/1690470#Nullsafe__1341) * [新增](http://www.hmoore.net/a173512/php_note/1690470#WeakMaphttpswwwphpnetmanualzhclassweakmapphp_1359)[WeakMap](https://www.php.net/manual/zh/class.weakmap.php)類 * [新增**ValueError**類](http://www.hmoore.net/a173512/php_note/1690470#ValueError_1360) * [任意數量的函數參數都可以用一個可變參數替換(只要類型兼容)](http://www.hmoore.net/a173512/php_note/1690470#_1361) * [static("后期靜態綁定"中) 可以作為返回類型](http://www.hmoore.net/a173512/php_note/1690470#static__1370) * [可以通過`$object::class`獲取類名,返回的結果和`get_class($object)`一致](http://www.hmoore.net/a173512/php_note/1690470#objectclassget_classobject_1378) * [可作為表達式使用`throw`](http://www.hmoore.net/a173512/php_note/1690470#throw_1379) * [在父類上聲明的私有方法不再對子類的方法強制執行任何繼承規則(最終私有構造函數除外)。 以下示例說明了哪些限制已被刪除:](http://www.hmoore.net/a173512/php_note/1690470#__1384) * [其他](http://www.hmoore.net/a173512/php_note/1690470#_1405) * [不向后兼容的變更](http://www.hmoore.net/a173512/php_note/1690470#_1415) * [**php8.1**](http://www.hmoore.net/a173512/php_note/1690470#php81_1425) 主要新特性一覽,詳情查看遷移日志 # **php5.4新特性** ## **增加短數組支持如:\[1, 2, 3, 4\]** ## **新增Trait** # **php5.5新特性** ## **新增yield關鍵字簡化生成器** **新增密碼加密及驗證** ~~~ //之前 //模擬input提交的密碼 $user_input = '12+#?345'; //crypt()函數不能正確處理加號。請首先對密碼使用urlencode,以確保登錄過程可以處理任何字符 $pass = urlencode($user_input)); $pass_crypt = crypt($pass); if ($pass_crypt == crypt($pass, $pass_crypt)) { echo "成功!有效的密碼"; } else { echo "無效的密碼"; } //當校驗密碼時,應該使用一個不容易被時間攻擊的字符串比較函數來比較crypt()的輸出與之前已知的哈希。出于這個目的,PHP5.6開始提供了hash_equals() $hashed_password = crypt('mypassword'); // 自動生成鹽值 /* 你應當使用 crypt() 得到的完整結果作為鹽值進行密碼校驗,以此來避免使用不同散列算法導致的問題。(如上所述,基于標準 DES 算法的密碼散列使用 2 字符鹽值,但是基于 MD5 算法的散列使用 12 個字符鹽值。)*/ if (hash_equals($hashed_password, crypt($user_input, $hashed_password))) { echo "Password verified!"; } //新特性 /** * 我們想要使用默認算法散列密碼 * 當前是 BCRYPT,并會產生 60 個字符的結果。 * * 請注意,隨時間推移,默認算法可能會有變化, * 所以需要儲存的空間能夠超過 60 字(255字不錯) * 強烈建議不要自己為這個函數生成鹽值(salt)。只要不設置,它會自動創建安全的鹽值 * password_hash 參數2有三個加密算法:PASSWORD_DEFAULT(默認),PASSWORD_BCRYPT ,PASSWORD_ARGON2I(php7.2加入) */ $hash=password_hash("rasmuslerdorf", PASSWORD_DEFAULT);//$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a if (password_verify('rasmuslerdorf', $hash)) { echo 'Password is valid!'; } else { echo 'Invalid password.'; } print_r(password_get_info ($hash)); //Array ( [algo] => 1 [algoName] => bcrypt [options] => Array ( [cost] => 10 ) ) ~~~ ![](https://img.kancloud.cn/3c/2d/3c2d9a4794eb4a29661e8fa507b0c4ab_1384x376.png) password\_hash方法我們無需關注salt,只需要將password\_hash返回的hash保存在數據庫就ok ~~~ $_POST['pwd']== 'rasmuslerdorf'; $password =$_POST['pwd']; //數據庫沒有就使用password_hash,數據庫有則查查出數據庫的hash if(!empty($res=findPwdToMysql($_POST['user'], $_POST['pwd']))){ $hash=$res; }else{ $hash=password_hash($password);//$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS savePwdTosql($hash); } // 當硬件性能得到改善時,cost 參數可以再修改(默認10) $options = array('cost' => 11); // 根據明文密碼驗證儲存的散列 if (password_verify($password, $hash)) { // 檢測是否有更新的可用散列算法 // 或者 cost 發生變化 if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) { // 如果是這樣,則創建新散列,替換舊散列 $newHash = password_hash($password, PASSWORD_DEFAULT, $options); } // 使用戶登錄setcookie() } ~~~ **訪問單個元素和字符** ~~~ //之前 $arr=[123]; $str='abc'; $arr[0]; $str[0]; //新特性: [123][0]; 'abc'[0]; ~~~ foreach控制結構現在支持通過[list()](https://www.php.net/manual/zh/function.list.php)構造將嵌套數組分離到單獨的變量 ~~~ //之前 $arr1=[1,2]; $arr2=[3,4]; list ($a, $b)=$arr1; list ($a, $b)=$arr2; //新特性: $array = [ [1, 2], [3, 4], ]; foreach ($array as list($a, $b)) { echo "A: $a; B: $b\n"; } 輸出: A: 1; B: 2 A: 3; B: 4 ~~~ ## **異常處理新增finally塊,`try{}catch{}finally{}`** finally塊中的代碼總是在try和catch塊之后執行,不管是否拋出了異常,也不管正常的執行是否繼續 # **php5.6 新特性** ## **可變數量的參數** 可變參數由 ... 語法實現;在 PHP 5.5 及更早版本中,使用函數 func\_num\_args(),func\_get\_arg(),和 func\_get\_args() ~~~ //5.6以前實現可變參數 function sum() { $acc = 0; foreach (func_get_args() as $n) { $acc += $n; } return $acc; } echo sum(1, 2, 3, 4); //新特性 function f($req, $opt = null, ...$params) { // $params 是一個包含了剩余參數的數組 printf('$req的值: %d; $opt的值: %d; $params的個數: %d;', $req, $opt, count($params)); echo gettype($params)."<br>"; } f(1);//$req的值: 1; $opt的值: 0; $params的個數: 0;array f(1, 2);//$req的值: 1; $opt的值: 2; $params的個數: 0;array f(1, 2, 3);//$req的值: 1; $opt的值: 2; $params的個數: 1;array f(1, 2, 3, 4);//$req的值: 1; $opt的值: 2; $params的個數: 2;array f(1, 2, 3, 4, 5);//$req的值: 1; $opt的值: 2; $params的個數: 3;array ~~~ 在調用函數的時候,使用...運算符, 將**數組**和**可遍歷**對象展開為函數參數。 在其他編程語言,比如 Ruby中,這被稱為連接運算符 ~~~ function add($a, $b, $c) { return $a + $b + $c; } //add(1,...[2, 3]) $operators = [2, 3]; echo add(1, ...$operators);//6 與add(1,2,3)效果一樣 ~~~ ## **使用表達式定義常量** ~~~ //之前只能使用靜態值定義常量 const ONE = 1; //現在可以用表達式定義常量 const TWO = ONE * 2; ~~~ ## **新增冪運算** 加入右連接運算符`**`來進行冪運算。 同時還支持簡寫的`**=`運算符,表示進行冪運算并賦值 ~~~ printf("2的3次方等于 %d\n", 2 ** 3);//2的3次方等于 8 ~~~ ## **新增\_\_debugInfo()魔術方法 當使用vardump打印類對象時觸發** ## **擴展了use 以前可以導入命名空間的類現在還可以導入函數及常量** ~~~ namespace Name\Space { const FOO = 42; function f() { echo __FUNCTION__."\n"; } } namespace { use const Name\Space\FOO; use function Name\Space\f; echo FOO."\n";//42 f();//Name\Space\f } ~~~ # **php7新特性** php7有三種方式創建空對象 ~~~ $obj1 = new \stdClass; // Instantiate stdClass object $obj2 = new class{}; // Instantiate anonymous class $obj3 = (object)[]; // Cast empty array to object var_dump($obj1); // object(stdClass)#1 (0) {} var_dump($obj2); // object(class@anonymous)#2 (0) {} var_dump($obj3); // object(stdClass)#3 (0) {} ~~~ $obj1和$obj3類型一樣但是不相等 ## **1.在use語句增加了group支持** ~~~ use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo }; ~~~ php7.2末尾可以留,而不會報錯 ~~~ use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo, }; ~~~ ## **2.類型約束與標量類型聲明(標量string、int、float和 bool)** 現在可在參數前加上參數類型,支持:具體類名接口名(php5.0),self(php5.0),array(php5.1),callable(php5.4),string(php7.0),int(php7.0),float(php7.0),bool(php7.0),iterable(php7.1),object(php7.2) > 特別注意 Closure類型約束的是匿名函數,匿名函數本身就是個Closure對象 > php有兩種模式強制模式(默認)和嚴格模式 > 聲明嚴格模式`declare(strict_types=1);`后,如果形參聲明為int那么參數是其他類型比如string時就會拋出致命錯誤,強制模式下的話會將string轉換為int而不會報錯 > 由上可知php5有可以約束array 類和接口 可調用函數 self 類型,我們可以簡單的認為php5類型約束是嚴格模式如`function foo(array $arr) {} foo(null)`會報錯提示給的參數不是指定的類型,但是參數為null時還是會報這個錯,解決辦法是將默認參數給個null`function foo(array $arr = null) {}`這樣fool(null)就不會報錯了 ~~~ class A{ public $name=null; public function demo(self $a){ var_dump($a); } public function __construct(){ $this->demo($this); //$this->demo(new stdClass()); // 致命錯誤 A::demo() must be an instance of A } } class B implements Iterator{//Iterator繼承Traversable public function current (){} //返回當前產生的值 public function key (){} //返回當前產生的鍵 public function next (){} // 生成器繼續執行 public function rewind (){} //重置迭代器 public function valid (){} //檢查迭代器是否被關閉 } new A(); //字符串 function demo(string $param){ var_dump(is_string($param)); } demo(1);//true demo(2.2); //true //整數 function demo1(int $param){ echo $param; var_dump(is_integer($param)); } demo1('1.1');//1 true demo1(1.1); //1 true //浮點數 function demo2(float $param){ echo $param; var_dump(is_float($param)); } demo2('1.2');//1.2 true demo2(1); //1 true //布爾值 function demo3(bool $param){ var_dump($param); var_dump(is_bool($param)); } demo3('a');// true true demo3(3.3);// true true //數組 function demo4(array $param){ var_dump($param); var_dump(is_array($param)); } demo4(['a']);//['a'] true //demo4('a');//demo4() must be of the type array //函數 function demo5(callable $param){ $param(); var_dump(is_callable($param,true)); } demo5(function(){echo 111;});// 111 true //對象 function demo6(object $param){ var_dump(is_object($param)); } demo6(new A());//true //迭代對象 function demo7(iterable $param){ var_dump($param instanceof Traversable); //var_dump(is_iterable($param)); } demo7(new B());//true demo7([1,2]);//false php7.2以前致命錯誤demo6() must be an instance of iterable //具體類名或接口名 function demo9(Exception $param){ print_r($param); } //demo9(new Exception('哈哈')); //demo9(new A());//致命錯誤 demo3() must be an instance of Exception, ~~~ ## **3.返回值類型聲明** 可用的類型與參數聲明中可用的類型相同。即支持:具體類名接口名(php5.0),self(php5.0),array(php5.1),callable(php5.4),string(php7.0),int(php7.0),float(php7.0),bool(php7.0),iterable(php7.1),void(php7.1),object(php7.2) > 注意指定類型后不能返回null,php7.1在類型前加?可解決此問題 ~~~ function demo($param):int{ return $param; } demo(null);//7.0致命錯誤 function demo1($param):?int{ return $param; } demo1(null);//php7.1類型前加上?就能接受及返回null function demo(?int $param):?int{ return $param; } demo(null);//php7.1類型前加上?就能接受及返回null ~~~ ## **4.三元運算新增null合并運算符??** 當第一個表達式的值不存在或者為null時返回第二個表達式的值,否則返回第一個表達式的值,詳情參看其他--三元運算章節 ~~~ $username = $_GET['user'] ?? 'nobody'; echo $username;//nobody ~~~ ## **5.太空船操作符(組合比較符)** 太空船操作符用于比較兩個表達式。當$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 // 字符串 echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 ~~~ ## **6.define支持定義數組** 自從PHP5.6后,使用const數組也能被定義為常量,define在PHP7中被實現 ## **7.支持[匿名類](https://www.php.net/manual/zh/language.oop5.anonymous.php)** 現在支持通過new class來實例化一個匿名類,這可以用來替代一些“用后即焚”的完整類定義 ~~~ interface Logger { public function log(string $msg); } class Application { private $logger; public function getLogger(): Logger { return $this->logger; } public function setLogger(Logger $logger) { $this->logger = $logger; } } $app = new Application; $app->setLogger(new class implements Logger { public function log(string $msg) { echo $msg; } }); var_dump($app->getLogger());//object(class@anonymous)#2 (0) {} ~~~ ## [**8.Unicode字符編碼表**](https://www.cnblogs.com/chris-oil/p/8677309.html) 中日韓統一表意文字(CJK Unified Ideographs),外加一些特殊的字符;用 \[ \\u2E80-\\uFE4F\] ~~~ echo '\u{2E80}';//\u{2E80} 必須雙引號 echo "\u{2E80}";//? ~~~ ## **9.增強之前的[assert()](https://www.php.net/manual/zh/function.assert.php)的方法** 簡單但卻最精確的定義一個*表達式*的方式就是“任何有值的東西” 早期assert是一個函數,php7是一個語法結構(在php語言中是用來判斷一個表達式是否成立。返回true or false;) 老版本的API出于兼容目的將繼續被維護,assert()現在是一個語言結構, 斷言在PHP 5,這必須是一個字符串或者一個布爾計算測試。在PHP 7中,這也可以是**返回值的任何表達式**,該值將被執行,其結果用于指示斷言是否成功或失敗 **php7新增的的ini配置如下:** **zend.assertions** 1:生成并執行代碼(開發模式) 0:生成代碼,但在運行時繞過它 \-1:不生成代碼(生產模式) > **zend.assertions=1** ## **assert.exception** //1:當斷言失敗時拋出,方法是拋出作為異常提供的對象,或者在沒有提供異常時拋出一個新的AssertionError對象 //0:使用或生成一個Throwable,如前所述,但只生成一個基于該對象的警告,而不是拋出它(兼容PHP 5行為) > **assert.exception=0** ~~~ assert(true == false); echo 'Hi!'; zend.assertions=0時輸出: Hi! zend.assertions=1并且assert.exception=0時輸出: Warning: assert(): assert(true == false) failed in - on line 2 Hi! zend.assertions=1并且assert.exception=1時輸出: Fatal error: Uncaught AssertionError: assert(true == false) in -:2 Stack trace: #0 -(2): assert(false, 'assert(true == ...') #1 {main} thrown in - on line 2 ~~~ ## **10.為unserialize()提供過濾** ~~~ //將所有對象分為__PHP_Incomplete_Class對象 $data = unserialize($foo, ["allowed_classes" => false]); //將所有對象分為__PHP_Incomplete_Class 對象 除了ClassName1和ClassName2 $data = unserialize($foo, ["allowed_classes" => ["ClassName1", "ClassName2"]); //默認行為,和 unserialize($foo)相同 $data = unserialize($foo, ["allowed_classes" => true]); ~~~ ## **11.增加Closure::call支持** Closure::call將一個閉包函數動態綁定到一個新的對象實例并調用執行該函數, ~~~ class Value { protected $value; public function __construct($value) { $this->value = $value; } public function getValue() { return $this->value; } } $three = new Value(3); $four = new Value(4); $closure = function ($delta) { var_dump($this->getValue() + $delta); }; $closure->call($three, 4); $closure->call($four, 4); // outputs int(7),int(8) ~~~ ~~~ class Test { public $name = "lixuan"; } //PHP7和PHP5.6都可以 $getNameFunc = function () { return $this->name; }; $name = $getNameFunc->bindTo(new Test, 'Test'); echo $name(); //PHP7可以,PHP5.6報錯 $getX = function () { return $this->name; }; echo $getX->call(new Test); ~~~ ## **12.新增整數除法函數** intdiv?接收兩個參數作為被除數和除數,返回他們相除結果的整數部分。 ~~~ // 7/2=3余1 值保留整數部分3 var_dump(intdiv(7, 2));//int(3) ~~~ ## **13.新增加的 IntlChar 類** 旨在暴露出更多的 ICU 功能。這個類自身定義了許多靜態方法用于操作多字符集的 unicode 字符。Intl是Pecl擴展,使用前需要編譯進PHP中,也可apt-get/yum/port install php5-intl ~~~ printf('%x', IntlChar::CODEPOINT_MAX); echo IntlChar::charName('@'); var_dump(IntlChar::ispunct('!')); ~~~ 以上例程會輸出:? 10ffff? COMMERCIAL AT? bool(true) CSPRNG ## **14.新增兩個跨平臺函數:**可用于生成salt、密鑰或初始化向量 兼容windows,linux或者其他大多數平臺,如果不兼容拋出異常 **random\_bytes**— 生成加密安全的偽隨機字節 ~~~ //隨機字節的長度設置為5 $bytes = random_bytes(5); print_r($bytes); //轉換為十六進制值 $hexadecimal = bin2hex($bytes); var_dump($hexadecimal);//類似8c7c0481d6的字符串 ~~~ 使用下面的函數來創建隨機的令牌,并且還從令牌中創建了一個salt。我在我的應用程序中使用它來防止CSRF攻擊 ~~~ function RandomToken($length = 32){ if(!isset($length) || intval($length) <= 8 ){ $length = 32; } if (function_exists('random_bytes')) { return bin2hex(random_bytes($length)); } if (function_exists('mcrypt_create_iv')) { return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)); } if (function_exists('openssl_random_pseudo_bytes')) { return bin2hex(openssl_random_pseudo_bytes($length)); } } function Salt(){ return substr(strtr(base64_encode(hex2bin(RandomToken(32))), '+', '.'), 0, 44); } echo (RandomToken()); echo '<br>'; echo Salt(); /* 調試上面的幾個函數 */ function RandomTokenDebug($length = 32){ if(!isset($length) || intval($length) <= 8 ){ $length = 32; } $randoms = array(); if (function_exists('random_bytes')) { $randoms['random_bytes'] = bin2hex(random_bytes($length)); } if (function_exists('mcrypt_create_iv')) { $randoms['mcrypt_create_iv'] = bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)); } if (function_exists('openssl_random_pseudo_bytes')) { $randoms['openssl_random_pseudo_bytes'] = bin2hex(openssl_random_pseudo_bytes($length)); } return $randoms; } echo '<br>'; print_r (RandomTokenDebug()); ~~~ **random\_int**(int`$min`,int`$max`) :int —生成加密安全的偽隨機整數 生成適合在非常重要的公正的結果情況下使用的加密隨機整數,例如在撲克游戲中洗牌時 ~~~ var_dump(random_int(100, 999));//int(248) var_dump(random_int(-1000, 0));//int(-898) ~~~ ## **15.新增preg\_replace\_callback\_array()函數,比preg\_replace\_callback()函數簡潔** 在 PHP 7 之前,當使用 preg\_replace\_callback() 函數的時候, 由于針對每個正則表達式都要執行回調函數,可能導致過多的分支代碼。 而使用新加的 preg\_replace\_callback\_array() 函數, 可以使得代碼更加簡潔。 現在,可以使用一個關聯數組來對每個正則表達式注冊回調函數, 正則表達式本身作為關聯數組的鍵, 而對應的回調函數就是關聯數組的值。 ## **16.session\_start()可以接受一個array作為參數** 現在,session\_start()函數可以接收一個數組作為參數,可以覆蓋php.ini中session的配置項。? 比如,把cache\_limiter設置為私有的,同時在閱讀完session后立即關閉 ~~~ session_start(['cache_limiter' => 'private', 'read_and_close' => true, ]); ~~~ ## **17.生成器中引入其他生成器** 在生成器中可以引入另一個或幾個生成器,只需要寫yield from functionName1 ~~~ function generator1() { yield 1; yield 2; yield from generator2(); yield from generator3(); } function generator2() { yield 3; yield 4; } function generator3() { yield 5; yield 6; } foreach (generator1() as $val) { echo $val, " "; } ~~~ ## **18.生成器可以返回表達式** 生成器(讀取超大文件很有用,節約內存) 它允許在生成器函數中通過使用 return 語法來返回一個表達式 (但是不允許返回引用值), 可以通過調用 Generator::getReturn() 方法來獲取生成器的返回值, 但是這個方法只能在生成器完成產生工作以后調用一次 ~~~ $gen = (function() { yield 1; yield 2; return 3; })(); foreach ($gen as $val) { echo $val, PHP_EOL;// 1 2 } //首先執行函數 該函數遇到yield停止并將該yied的值發送給foreach echo $gen->getReturn(), PHP_EOL;//3 結果: 1 2 3 ~~~ php全局保留字可以聲明使用 ~~~ class View { public function include(View $view) { //... //include關鍵字可以當普通字符串關鍵字一樣被使[其他](%E5%85%B6%E4%BB%96.md)用 } } ~~~ 允許在克隆表達式上訪問對象成員,例如:*(clone $foo)->bar()*。 # **php7.1新特性** ## **參數和返回類型支持null,前提是在類型前加?** ~~~ function test1(?string $name) { var_dump($name); } //在默認非嚴格模式下,標量string、int、float和 bool 之間會強制轉化,與php7相比php7.1可接受null test1('dash');//'dash' test1(null);//NULL test1(30);//'30' test1(30.1);//'30.1' test1(true);//'1' test1([1,2]);//致命錯誤 test1(new stdClass);//致命錯誤 function test1($name):?string { return $name; } echo gettype(test1('dash'));//string echo gettype(test1(null));//NULL echo gettype(test1(30));//string echo gettype(test1(30.1));//string echo gettype(test1(true));//string test1([1,2]);//致命錯誤 test1(new stdClass);//致命錯誤 ~~~ ## **php7.1返回類型新增void** ~~~ function test(): void { return 'hello'; } test();//致命錯誤 function test1(): void { return null; } test1();//致命錯誤 function test2(): void { return ''; } test2();//致命錯誤 function test3(): void { return; } test3();//正常 function test4(): void { //無返回值 } test4();//正常 ~~~ ## **短數組語法(*\[\]*)現在作為list()語法的一個備選項,可以用于將數組的值賦給一些變量(包括在*foreach*中)** ~~~ $data = [ [1, 'Tom'], [2, 'Fred'], ]; //php之前支持格式 list($id1, $name1) = $data[0]; foreach ($data as list($id, $name)) { // logic here with $id and $name } //php7新增的短數組[]格式 [$id1, $name1] = $data[0]; foreach ($data as [$id, $name]) { // logic here with $id and $name } ~~~ PHP 5 里,list() 從最右邊的參數開始賦值; PHP 7 里,list() 從最左邊的參數開始賦值 ~~~ $info = array('coffee', 'brown', 'caffeine'); list($a[0], $a[1], $a[2]) = $info; print_r($a); php5輸出:[2=>'caffeine',1=>'brown',0=>'coffee'] php7輸出:[0=>'coffee',1=>'brown',2=>'caffeine'] ~~~ 在 PHP 7.1.0 之前的版本,list() 僅能用于數字索引的數組,并假定數字索引從 0 開始 從 PHP 7.1.0 開始,list() 可以包含顯式的鍵,可賦值到任意表達式。 可以混合使用數字和字符串鍵。但是不能混合有鍵和無鍵不能混用 ~~~ $data = [ ["id" => 1, "name" => 'Tom'], ["id" => 2, "name" => 'Fred'], ]; foreach ($data as ["id" => $id, "name" => $name]) { echo "id: $id, name: $name\n";//id: 1, name: Tom id: 2, name: Fred } echo PHP_EOL; list(1 => $second, 3 => $fourth) = [1, 2, 3, 4]; echo $second.$fourth.PHP_EOL;//2 4 ~~~ ## **字符串偏移量可以為負,表示為一個從字符串結尾開始的偏移量** ~~~ var_dump("abcdef"[-2]);//e //b在abcdef首次出現的位置 從結尾倒數第5個偏移開始查找 echo strpos('abcdef','b', -5);//1 a b c d e f 0 1 2 3 4 5 -6 -5 -4 -3 -2 -1 ~~~ ## **字符串負偏移在簡單的變量解析語法中也支持能了** ~~~ $string = 'bar'; echo "The last character of '$string' is '$string[-1]'.\n";//The last character of 'bar' is 'r'. ~~~ ## **對服務器推送的支持現在已經被加入到 CURL 擴展(v7.46)中** ~~~ $transfers = 1; $callback = function($parent_ch, $pushed_ch, array $headers) use (&$transfers) { $transfers++; // 增量,以跟蹤并發請求的數量 return CURL_PUSH_OK; }; $mh = curl_multi_init(); curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $callback); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://localhost:8080/index.html"); curl_setopt($ch, CURLOPT_HTTP_VERSION, 3); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 調式/局部填充 //curl_setopt($ch, CURLOPT_VERBOSE, 1); // 是否會輸出curl調試信息 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // self-signed cert curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // self-signed cert curl_multi_add_handle($mh, $ch); $active = null; do { $status = curl_multi_exec($mh, $active); do { $info = curl_multi_info_read($mh); if (false !== $info && $info['msg'] == CURLMSG_DONE) { $handle = $info['handle']; if ($handle !== null) { $transfers--; // 減量 剩余請求 $out = curl_multi_getcontent($info['handle']); // 響應體 curl_multi_remove_handle($mh, $handle); curl_close($handle); } } } while ($info); } while ($transfers); curl_multi_close($mh); ~~~ ## **異步信號處理** 一個新的名為 pcntl\_async\_signals() 的方法現在被引入, 用于啟用無需 ticks (這會帶來很多額外的開銷)的異步信號處理。 ~~~ pcntl_async_signals(true); // 打開異步信號 pcntl_signal(SIGHUP, function($sig) { echo "SIGHUP\n"; }); posix_kill(posix_getpid(), SIGHUP); 以上例程會輸出: SIGHUP ~~~ ## **新增Closure::fromCallable() 將callables轉為閉包** Closure新增了一個靜態方法,用于將callable快速地 轉為一個Closure 對象。 ~~~ class Test { public function exposeFunction() { return Closure::fromCallable([$this, 'privateFunction']); } private function privateFunction($param) { var_dump($param); } } //((new Test)->exposeFunction())('some value'); $privFunc = (new Test)->exposeFunction(); $privFunc('some value');//some value ~~~ # **php7.2新特性** ## **新的對象類型** 這種新的對象類型, object, 引進了可用于逆變(contravariant)參數輸入和協變(covariant)返回任何對象類型 ~~~ function test(object $obj) : object { return new SplQueue(); } test(new StdClass()); ~~~ ## **既可以通過 php.ini 也可以運行時通過 dl(string $library): bool載入一個 PHP 擴展** 在 安全模式(php5.4廢除),總是無法使用 dl() 不推薦,存在安全風險 如果加載模塊的功能是無效或者禁用的(既可以通過設置關閉 enable\_dl(僅對 Apache 模塊版本的 PHP 有效) 設置 ~~~ // 加載一個擴展的例子,基于操作系統 if (!extension_loaded('sqlite')) {//檢查一個擴展是否已經加載 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { dl('php_sqlite.dll'); } else { dl('sqlite.so'); } } // 或者,使用常量 PHP_SHLIB_SUFFIX if (!extension_loaded('sqlite')) { $prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : ''; dl($prefix . 'sqlite.' . PHP_SHLIB_SUFFIX); } ~~~ ## **允許重寫抽象方法** 當一個抽象類繼承于另外一個抽象類的時候,繼承后的抽象類可以重寫被繼承的抽象類的抽象方法 ~~~ abstract class A { abstract function test(string $s); } abstract class B extends A { // 覆蓋 - still maintaining contravariance for parameters and covariance for return abstract function test($s) : int; } ~~~ ## **重寫方法和接口實現的參數類型現在可以省略** ~~~ interface A { public function Test(array $input); } class B implements A { public function Test($input){} // 省略了$input的類型 } ~~~ # **php7.3新特性** ## **更靈活的`Heredoc`和`Nowdoc`語法** ~~~ //heredoc可以解析變量,nowdoc則不能解析變量 $name='dash'; //原heredoc $str=<<<STR 這是文本第一行 這是文本第二行.{$name}over! STR; echo $str;//這是文本第一行 這是文本第二行.dashover! //原nowdoc $str = <<<'EOD' Example of string spanning multiple lines using nowdoc syntax.{$name}over! EOD; echo $str;//Example of string spanning multiple lines using nowdoc syntax.{$name}over! //可以使用縮進,使用縮進時doc內容的每行都會跳過相應的縮進 (下例兩行的縮進都被剝除了) $str=<<<STR 這是文本第一行 | 這是文本第二行 STR; | STR; echo $str;// 這是文本第一行 | 這是文本第二行 STR; | 兩行的縮進都被剝除了 //結束標記不再需要獨立一行 $str=<<<STR 這是文本第一行 這是文本第二行 STR;echo $str;//這是文本第一行 這是文本第二行 //在某些情況下不用緊跟分號了 $data = ["元素", <<<STR 這是文本第一行 這是文本第二行 STR, 42,]; print_r($data);//Array ( [0] => 元素 [1] => 這是文本第一行 這是文本第二行 [2] => 42 ) $str=<<<STR 這是文本第一行 這是文本第二行 STR echo $str;//這中情況就會報錯 ~~~ ## **數組析構與list結構支持引用賦值** $v = \[10, 20\]; \[$a, &$b\] = $v;//短語法等同list($a, &$b)=$v; $b += 10; var\_dump($v, $a, $b);//array(2) { \[0\]=> int(10) \[1\]=> &int(30) } int(10) int(30) ## \*\* instanceof 運算符支持字面量語法\*\* instanceof 的第一個運算數支持字面量,非對象型字面量檢測的結果為 false var\_dump("literal" instanceof stdClass);//false var\_dump(42 instanceof stdClass);//false var\_dump(new stdClass() instanceof stdClass);//true ## **支持調用時參數的末尾跟隨逗號,但是定義是不行的** function methodName($p1, $p2) { var\_dump($p1, $p2); } methodName(10, 20, );//10 20 ## **BC 數學函數** bcscale() 函數支持獲取當前任意BC(精度的數學擴展)函數所使用的 scale。 bcscale(3);//設置所有bc數學函數的默認小數點保留位數 var\_dump(bcscale());//3 ## **廢棄大小寫不敏感的常量** 將 TRUE 作為第三個參數傳遞給 define() 會導致一個廢棄警告 ## **命名捕獲支持** mb\_ereg\_ \*系列函數現在支持命名捕獲。類似于mb\_ereg()的匹配函數現在將使用其組號和名稱返回命名捕獲,類似于PCRE: ~~~ mb_ereg('(?<word>\w+)', '國', $matches); print_r($matches);//Array ( [0] => [0 => "國", 1 => "國", "word" => "國"]; mb_ereg('(?<word>\w+)', '國<=>家', $matches); print_r($matches);//Array ( [0] => [0 => "國", 1 => "國", "word" => "國"]; mb_ereg('(?<word>\w+)', '國家', $matches); print_r($matches);//Array ( [0] => 國家 [1] => 國家 [word] => 國家 ) ~~~ 此外,mb\_ereg\_replace()現在支持 \\k<>和\\k''表示法來引用替換字符串中的命名捕獲: ~~~ //mb_ereg_replace ($pattern , $replacement , $string中匹配) //在string中匹配pattern,匹配成功則替換成replacement $str=mb_ereg_replace('\s*(?<word>\w+)\s*', "_\k<word>_\k'word'_", ' foo '); echo $str;// => "_foo_foo_" ~~~ # **php7.4新特性** ## **預加載** `PHP`預加載可以極大的提高性能 * 優點:在`PHP 7.4`以前,如果你使用了框架來開發,每次請求文件就必須加載和重新編譯。預加載在框架啟動時在內存中加載文件,而且在后續請求中永久有效。 * 缺點:性能的提升會在其他方面花費很大的代價,每次預加載的文件發生改變時,框架需要重新啟動。 ## **類屬性現在支持類型聲明** 除了`void`和`callable`外,所有的類型都支持 因此,我們可以放心使用`bool`,`int`,`float`,`string`,`array`,`object`,`iterable`,`self`,`parent` ~~~ class User { public int $id; public string $name; public ?Foo $foo; } ~~~ ## **短閉包函數** ~~~ array_map (function($arr1_value, $arr2_value, $arrN_value){ //return $arr1_value.$arr2_value.$arrN_value; }, $arr1, $arr2, $arrN ); //原有特性 function cube($n){ return ($n * $n * $n); } $a = [1, 2, 3, 4, 5]; $b = array_map('cube', $a); print_r($b); //新特性 $a = [1, 2, 3, 4, 5]; $res = array_map(fn($n) => $n * $n * $n, $a); print_r($res); $a = [1, 2]; $b = [3, 4, 5]; $res = array_map(fn($av,$bv) => $av*$bv, $a,$b); print_r($res); $a = [1, 2]; $b = [3, 4, 5]; $res = array_map(fn(?int $av,?int $bv): int => $av*$bv, $a,$b); print_r($res); //如果你想通過引用返回一個值,應該使用以下語法 fn&($x) => $x //總結: //它們以fn關鍵字開始 //它們只能有一個表達式,即return語句 //不允許return關鍵字 //參數和返回類型可以是限定類型 ~~~ ## **Null 合并運算符** ~~~ $data['date'] ??= new DateTime(); //相當于之前的 $data['date'] = $data['date'] ?? new DateTime(); 或: if (!isset($data['date'])) { $data['date'] = new DateTime(); } ~~~ ## **數組擴展運算符(展開運算符)** 現在你可以在數組中使用展開運算符: **注意**:只對數字索引有效 ~~~ $arrayA = [1, 2, 3]; $arrayB = [4, 5]; $result = [0, ...$arrayA, ...$arrayB, 6 ,7]; // [0, 1, 2, 3, 4, 5, 6, 7] ~~~ ## **自定義對象序列化** 添加了兩個新的魔術方法:`__serialize`?和`__unserialize` ## **數字分隔符** 允許使用下劃線更直觀的分隔數值 ~~~ $unformattedNumber = 107925284.88; //新特性 $formattedNumber = 107_925_284.88; ~~~ ## **支持反射引用** `PHP 7.4`將會新增`ReflectionReference`類 ## **改進的類型差異(協變返回和逆變參數)** [協變和逆變](https://link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E5%258D%258F%25E5%258F%2598%25E4%25B8%258E%25E9%2580%2586%25E5%258F%2598) [百度百科的解釋](https://link.zhihu.com/?target=https%3A//baike.baidu.com/item/%25E5%258D%258F%25E5%258F%2598) 協變與逆變(Covariance and contravariance )是在計算機科學中,描述具有父/子型別關系的多個型別通過型別構造器、構造出的多個復雜型別之間是否有父/子型別關系的用語。 * Invariant (不變): 包好了所有需求類型 * Covariant (協變):類型從通用到具體 * Contravariant (逆變): 類型從具體到通用目前,PHP 主要具有`Invariant`的參數類型,并且大多數是`Invariant`的返回類型,這就意味著當我是 T 參數類型或者返回類型時,子類也必須是 T 的參數類型或者返回類型。但是往往會需要處理一些特殊情況,比如具體的返回類型,或者通用的輸入類型。而[RFC](https://link.zhihu.com/?target=https%3A//wiki.php.net/rfc/covariant-returns-and-contravariant-parameters)的這個提案就提議,PHP7.4 添加協變返回和逆變參數,以下是提案給出來的例子:協變返回: ~~~ class Parent {} class Child extends Parent {} class A { public function covariantReturnTypes(): Parent { /* … */ } } class B extends A { public function covariantReturnTypes(): Child { /* … */ } } ~~~ ## **箭頭函數** 匿名函數和箭頭函數都是[](https://www.php.net/manual/zh/class.closure.php)[Closure](https://www.php.net/manual/zh/class.closure.php)類的實現 箭頭函數的基本語法為`fn (argument_list) => expr` ~~~ $y = 1; $fn1 = fn($x) => $x + $y; // 相當于 using $y by value: $fn2 = function ($x) use ($y) { return $x + $y; }; var_export($fn1(3)); //箭頭函數自動捕捉變量的值,即使在嵌套的情況下 $z = 1; $fn = fn($x) => fn($y) => $x * $y + $z; var_export($fn(5)(10));// 輸出 51 //合法的箭頭函數例子 fn(array $x) => $x; static fn(): int => $x; fn($x = 42) => $x; fn(&$x) => $x; fn&($x) => $x; fn($x, ...$rest) => $rest; //示例 #4 來自外部范圍的值不能在箭頭函數內修改 $x = 1; $fn = fn() => $x++; // 不會影響 x 的值 $fn(); var_export($x); // 輸出 1 ~~~ # **php8** ## **參數最后可尾隨`,`** ~~~ function demo($a,$b,){} ~~~ ## 不推薦在可選參數之后傳遞強制參數,但null除外 如果帶有默認值的參數后面跟著一個必要的參數,那么默認值就會無效。這在 PHP 8.0.0 中已被廢棄,通常可以通過刪除默認值,不影響現有功能: ~~~ //不推薦 function demo($a=[],$b){} demo(1);//$a為可選參數,他后面跟的是一個必要參數$b,k可選參數$a的默認值則在8.0之前是無效的 //可行替代方案 function demo($a, $b){} //null時除外 function demo($a=null,$b){} //官方推薦 function demo(?array $a){} ~~~ ## **新增注解功能** [https://www.php.net/manual/zh/language.attributes.overview.php](https://www.php.net/manual/zh/language.attributes.overview.php) ## **在構造函數中聲明類的屬性** ~~~ class Point { protected int $x; protected int $y; public function __construct(int $x, int $y = 0) { $this->x = $x; $this->y = $y; } //8.0構造器提升類屬性 public function __construct(protected int $x, protected int $y = 0) { } } // 兩個參數都傳入 $p1 = new Point(4, 5); // 僅傳入必填的參數。 $y 會默認取值 0。 $p2 = new Point(4); // 使用命名參數(PHP 8.0 起): $p3 = new Point(y: 5, x: 4); ~~~ ## **新增聯合類型** [mixed](https://www.php.net/manual/zh/language.types.declarations.php#language.types.declarations.mixed)等同于[聯合類型](https://www.php.net/manual/zh/language.types.declarations.php#language.types.declarations.union)object|resource|array|string|int|float|bool|null。PHP 8.0.0 起可用。 ## **新增`match`表達式** `match`表達式跟`switch`語句相似,但是有以下關鍵區別: * 它會像三元表達式一樣求值 * `match`比較分支值,使用了嚴格比較 (`===`), 而 switch 語句使用了松散比較。 * `match`表達式會返回一個值。 * `match`的分支不會像`switch`語句一樣, 落空時執行下個 case。 * `match`表達式必須徹底列舉所有情況。如果主體表達式不能被任意分支條件處理, 會拋出**UnhandledMatchError** ~~~ $food = 'cake'; $return_value = match ($food) { 'apple' => 'This food is an apple', 'bar' => 'This food is a bar', 'cake' => 'This food is a cake', }; var_dump($return_value);//This food is a cake //逐個檢測匹配分支。一開始不會執行代碼。 只有在所有之前的條件不匹配主體表達式時,才會執行剩下的條件表達式。 只會執行返回的表達式所對應的匹配條件表達式 $result = match ($x) { foo() => ..., $this->bar() => ..., // 如果 foo() === $x,不會執行 $this->bar() $this->baz => beep(), // 只有 $x === $this->baz 時才會執行 beep() // 等等 }; //`match`表達式分支可以通過逗號分隔,包含多個表達式。 這是一個邏輯 OR,當多個分支表達式右側相同時,就可以用這種縮寫 $result = match ($x) { // 匹配分支: $a, $b, $c => 5, // 等同于以下三個分支: $a => 5, $b => 5, $c => 5, }; //`default`模式是個特殊的條件。 當之前的條件都不匹配時,會匹配到該模式 //多個 default 模式將會觸發**`E_FATAL_ERROR`**錯誤 $expressionResult = match ($condition) { 1, 2 => foo(), 3, 4 => bar(), default => baz(), }; //**針對整數范圍,使用寬泛的表達式匹配分支** $age = 23; $result = match (true) { $age >= 65 => 'senior', $age >= 25 => 'adult', $age >= 18 => 'young adult', default => 'kid', }; var_dump($result);//young adult //**針對字符串內容,使用寬泛的表達式匹配分支** $text = 'Bienvenue chez nous'; $result = match (true) { str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', // ... }; var_dump($result);//fr //表達式存在未處理的示例 $condition = 5; try { match ($condition) { 1, 2 => foo(), 3, 4 => bar(), }; } catch (\UnhandledMatchError $e) { var_dump($e); } ~~~ ## **新增Nullsafe 運算符(`?->`)** nullsafe 操作符和->原來的屬性、方法訪問是一致的: 對象引用解析(dereference)為\*\*`null`**時不拋出異常,而是返回**`null`\*\*。 并且如果是鏈式調用中的一部分,剩余鏈條會直接跳過.此操作的結果,類似于在每次訪問前使用 is\_null() 函數判斷方法和屬性是否存在,但更加簡潔 ~~~ // 自 PHP 8.0.0 起可用 $result = $repository?->getUser(5)?->name; // 上邊那行代碼等價于以下代碼 if (is_null($repository)) { $result = null; } else { $user = $repository->getUser(5); if (is_null($user)) { $result = null; } else { $result = $user->name; } } ~~~ ## 新增[WeakMap](https://www.php.net/manual/zh/class.weakmap.php)類 ## 新增**ValueError**類 ## 任意數量的函數參數都可以用一個可變參數替換(只要類型兼容) ~~~ class A { public function method(int $many, string $parameters, $here) {} } class B extends A { public function method(...$everything) {} } ~~~ ## static("后期靜態綁定"中) 可以作為返回類型 ~~~ class Test { public function create(): static { return new static(); } } ~~~ ## 可以通過`$object::class`獲取類名,返回的結果和`get_class($object)`一致 ## 可作為表達式使用`throw` ~~~ $fn = fn() => throw new Exception('Exception in arrow function'); $user = $session->user ?? throw new Exception('Must have user'); ~~~ ## 在父類上聲明的私有方法不再對子類的方法強制執行任何繼承規則(最終私有構造函數除外)。 以下示例說明了哪些限制已被刪除: ~~~ class ParentClass { private function method1() {} private function method2() {} private static function method3() {} // Throws a warning, as "final" no longer has an effect: private final function method4() {} } class ChildClass extends ParentClass { // All of the following are now allowed, even though the modifiers aren't // the same as for the private methods in the parent class. public abstract function method1() {} public static function method2() {} public function method3() {} public function method4() {} } ~~~ ## 其他 * [`new`](https://www.php.net/manual/zh/language.oop5.basic.php#language.oop5.basic.new)、[`instanceof`](https://www.php.net/manual/zh/language.operators.type.php)可用于任何表達式, 用法為`new (expression)(...$args)`和`$obj instanceof (expression)`。 * 添加對一些變量語法一致性的修復,例如現在能夠編寫`Foo::BAR::$baz`。 * 添加[Stringable](https://www.php.net/manual/zh/class.stringable.php)interface, 當一個類定義[\_\_toString()](https://www.php.net/manual/zh/language.oop5.magic.php#object.tostring)方法后會自動實現該接口。 * Trait 可以定義私有抽象方法(abstract private method)。 類必須實現 trait 定義的該方法。 * 新增[get\_resource\_id()](https://www.php.net/manual/zh/function.get-resource-id.php) ## 不向后兼容的變更 | Comparison | Before | After | | --- | --- | --- | | `0 == "0"` | **`true`** | **`true`** | | `0 == "0.0"` | **`true`** | **`true`** | | `0 == "foo"` | **`true`** | **`false`** | | `0 == ""` | **`true`** | **`false`** | | `42 == " 42"` | **`true`** | **`true`** | | `42 == "42foo"` | **`true`** | **`false`** | `(real)`和`(unset)`轉換已被移除。 # **php8.1**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看