php7 php5.6 array,[转]php5.6 升级到php7及变化
不向后兼容的變更
錯誤和異常處理相關的變更
在 PHP 7 中,很多致命錯誤以及可恢復的致命錯誤,都被轉換為異常來處理了。 這些異常繼承自?Error?類,此類實現了?Throwable?接口 (所有異常都實現了這個基礎接口)。
這也意味著,當發生錯誤的時候,以前代碼中的一些錯誤處理的代碼將無法被觸發。 因為在 PHP 7 版本中,已經使用拋出異常的錯誤處理機制了。 (如果代碼中沒有捕獲?Error?異常,那么會引發致命錯誤)。
PHP 7 中的錯誤處理的更完整的描述,請參見?PHP 7 錯誤處理。 本遷移指導主要是列出對兼容性有影響的變更。
拋出?Error?對象時,如果?set_exception_handler()?里的異常處理代碼聲明了類型?Exception?,將會導致 fatal error。
想要異常處理器同時支持 PHP5 和 PHP7,應該刪掉異常處理器里的類型聲明。如果代碼僅僅是升級到 PHP7,則可以把類型?Exception?替換成?Throwable。
//?PHP?5?時代的代碼將會出現問題
function?handler(Exception?$e)?{?...?}
set_exception_handler('handler');
//?兼容?PHP?5?和?7
function?handler($e)?{?...?}
//?僅支持?PHP?7
function?handler(Throwable?$e)?{?...?}
?>
當內部構造器失敗的時候,總是拋出異常
在之前版本中,如果內部類的構造器出錯,會返回?NULL?或者一個不可用的對象。 從 PHP 7 開始,如果內部類構造器發生錯誤, 那么會拋出異常。
解析錯誤會拋出?ParseError?異常
解析錯誤會拋出?ParseError?異常。 對于?eval()?函數,需要將其包含到一個?catch?代碼塊中來處理解析錯誤。
E_STRICT 警告級別變更
原有的?E_STRICT?警告都被遷移到其他級別。?E_STRICT?常量會被保留,所以調用?error_reporting(E_ALL|E_STRICT)?不會引發錯誤。
E_STRICT?警告級別變更
場景新的級別/行為
將資源類型的變量用作鍵來進行索引E_NOTICE
抽象靜態方法不再警告,會引發錯誤
重復定義構造器函數不再警告,會引發錯誤
在繼承的時候,方法簽名不匹配E_WARNING
在兩個 trait 中包含相同的(兼容的)屬性不再警告,會引發錯誤
以非靜態調用的方式訪問靜態屬性E_NOTICE
變量應該以引用的方式賦值E_NOTICE
變量應該以引用的方式傳遞(到函數參數中)E_NOTICE
以靜態方式調用實例方法E_DEPRECATED
關于變量處理的變化
PHP 7 現在使用了抽象語法樹來解析源代碼。這使得許多由于之前的PHP的解釋器的限制所不可能實現的改進得以實現。 但出于一致性的原因導致了一些特殊例子的變動,而這些變動打破了向后兼容。 在這一章中將詳細介紹這些例子。
關于間接使用變量、屬性和方法的變化
對變量、屬性和方法的間接調用現在將嚴格遵循從左到右的順序來解析,而不是之前的混雜著幾個特殊案例的情況。 下面這張表說明了這個解析順序的變化。
間接調用的表達式的新舊解析順序
表達式PHP 5 的解析方式PHP 7 的解析方式
$$foo['bar']['baz']${$foo['bar']['baz']}($$foo)['bar']['baz']
$foo->$bar['baz']$foo->{$bar['baz']}($foo->$bar)['baz']
$foo->$bar['baz']()$foo->{$bar['baz']}()($foo->$bar)['baz']()
Foo::$bar['baz']()Foo::{$bar['baz']}()(Foo::$bar)['baz']()
使用了舊的從右到左的解析順序的代碼必須被重寫,明確的使用大括號來表明順序(參見上表中間一列)。 這樣使得代碼既保持了與PHP 7.x的前向兼容性,又保持了與PHP 5.x的后向兼容性。
這同樣影響了?global?關鍵字。如果需要的話可以使用大括號來模擬之前的行為。
function?f()?{
//?Valid?in?PHP?5?only.
global?$$foo->bar;
//?Valid?in?PHP?5?and?7.
global?${$foo->bar};
}
?>
關于list()處理方式的變更
list()?不再以反向的順序來進行賦值
list()?現在會按照變量定義的順序來給他們進行賦值,而非反過來的順序。 通常來說,這只會影響list()?與數組的[]操作符一起使用的案例,如下所示:
list($a[],?$a[],?$a[])?=?[1,?2,?3];
var_dump($a);
?>
Output of the above example in PHP 5:
array(3) {
[0]=>
int(3)
[1]=>
int(2)
[2]=>
int(1)
}
Output of the above example in PHP 7:
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
總之,我們推薦不要依賴list()的賦值順序,因為這是一個在未來也許會變更的實現細節。
空的list()賦值支持已經被移除
list()?結構現在不再能是空的。如下的例子不再被允許:
list()?=?$a;
list(,,)?=
$a;
list(
$x,?list(),?$y)?=?$a;
?>
list()?不再能解開字符串(string)變量。 你可以使用str_split()來代替它。
Array ordering when elements are automatically created during by reference assignments has changed
The order of the elements in an array has changed when those elements have been automatically created by referencing them in a by reference assignment. For example:
$array
=?[];
$array["a"]?=&?$array["b"];
$array["b"]?=?1;
var_dump($array);
?>
Output of the above example in PHP 5:
array(2) {
["b"]=>
&int(1)
["a"]=>
&int(1)
}
Output of the above example in PHP 7:
array(2) {
["a"]=>
&int(1)
["b"]=>
&int(1)
}
函數參數附近的括號不再影響行為
在 PHP 5中,在以引用方式傳遞函數參數時,使用冗余的括號對可以隱匿嚴格標準 的警告。現在,這個警告總會觸發。
function?getArray()?{
return?[
1,?2,?3];
}
function
squareArray(array?&$a)?{
foreach?(
$a?as?&$v)?{
$v?**=?2;
}
}
//?Generates?a?warning?in?PHP?7.
squareArray((getArray()));
?>
以上例程會輸出:
Notice: Only variables should be passed by reference in /tmp/test.php on line 13
foreach發生了細微的變化,控制結構, 主要圍繞陣列的內部數組指針和迭代處理的修改。
foreach不再改變內部數組指針
在PHP7之前,當數組通過?foreach?迭代時,數組指針會移動。現在開始,不再如此,見下面代碼
$array
=?[0,?1,?2];
foreach?(
$array?as?&$val)?{
var_dump(current($array));
}
?>
Output of the above example in PHP 5:
int(1)
int(2)
bool(false)
Output of the above example in PHP 7:
int(0)
int(0)
int(0)
foreach?通過值遍歷時,操作的值為數組的副本
當默認使用通過值遍歷數組時,foreach?實際操作的是數組的迭代副本,而非數組本身。這就意味著,foreach 中的操作不會修改原數組的值。
foreach通過引用遍歷時,有更好的迭代特性
當使用引用遍歷數組時,現在?foreach?在迭代中能更好的跟蹤變化。例如,在迭代中添加一個迭代值到數組中,參考下面的代碼:
$array
=?[0];
foreach?(
$array?as?&$val)?{
var_dump($val);
$array[1]?=?1;
}
?>
Output of the above example in PHP 5:
int(0)
Output of the above example in PHP 7:
int(0)
int(1)
非Traversable?對象的遍歷
迭代一個非Traversable對象將會與迭代一個引用數組的行為相同。 這將導致在對象添加或刪除屬性時,foreach通過引用遍歷時,有更好的迭代特性也能被應用
Changes to?integer?handling
無效的八進制字符(Invalid octal literals)
在之前,一個八進制字符如果含有無效數字,該無效數字將被靜默刪節(0128?將被解析為?012). 現在這樣的八進制字符將產生解析錯誤。
負位移運算(Negative bitshifts)
以負數形式進行的位移運算將會拋出一個?ArithmeticError:
var_dump
(1?>>?-1);
?>
Output of the above example in PHP 5:
int(0)
Output of the above example in PHP 7:
Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2
Stack trace:
#0 {main}
thrown in /tmp/test.php on line 2
超范圍后產生位移
超出?integer?位寬的位移操作(無論哪個方向)將始終得到 0 作為結果。在從前,這一操作是結構依賴的。
string處理上的調整
十六進制字符串不再被認為是數字
含十六進制字符串不再被認為是數字。例如:
var_dump
("0x123"?==?"291");
var_dump(is_numeric("0x123"));
var_dump("0xe"?+?"0x1");
var_dump(substr("foo",?"0x1"));
?>
Output of the above example in PHP 5:
bool(true)
bool(true)
int(15)
string(2) "oo"
Output of the above example in PHP 7:
bool(false)
bool(false)
int(0)
Notice: A non well formed numeric value encountered in /tmp/test.php on line 5
string(3) "foo"
filter_var()?函數可以用于檢查一個?string?是否含有十六進制數字,并將其轉換為integer:
$str
=?"0xffff";
$int?=?filter_var($str,?FILTER_VALIDATE_INT,?FILTER_FLAG_ALLOW_HEX);
if?(
false?===?$int)?{
throw?new
Exception("Invalid?integer!");
}
var_dump($int);?//?int(65535)
?>
\u{?可能引起錯誤
由于新的?Unicode codepoint escape syntax語法, 緊連著無效序列并包含\u{?的字串可能引起致命錯誤。 為了避免這一報錯,應該避免反斜杠開頭。
被移除的函數(Removed functions)
所有的 ereg* 函數
所有?ereg?系列函數被刪掉了。?PCRE?作為推薦的替代品。
所有 ext/mysql 函數
所有?ext/mysql?函數已被刪掉了。 如何選擇不同的 MySQL API,詳情請見?選擇 MySQL API。
所有 ext/mssql 函數
所有?ext/mssql?函數已被刪掉了。 替代品的列表,參見?MSSQL 介紹。
dl()?in PHP-FPM
dl()在 PHP-FPM 不再可用,在 CLI 和 embed SAPIs 中仍可用。
GD?Type1 functions
Support for PostScript Type1 fonts has been removed from the GD extension, resulting in the removal of the following functions:
推薦使用 TrueType 字體和相關的函數作為替代。
被移除掉的 INI 配置指令
被移除的功能
以下 INI 配置指令已經被移除,同時移除的還有其對應的功能
xsl.security_prefs
xsl.security_prefs?指令被移除 在預處理的時候,取而代之的方法?XsltProcessor::setSecurityPrefs()?應該被調用到
其他向后兼容相關的變更
new 操作符創建的對象不能以引用方式賦值給變量
new?語句創建的對象不能 以引用的方式賦值給變量。
class?C?{}
$c?=&?new?C;
?>
Output of the above example in PHP 5:
Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3
Output of the above example in PHP 7:
Parse error: syntax error, unexpected 'new' (T_NEW) in /tmp/test.php on line 3
無效的類、接口以及 trait 命名
不能以下列名字來命名類、接口以及 trait:
NULL
TRUE
FALSE
此外,也不要使用下列的名字來命名類、接口以及 trait。雖然在 PHP 7.0 中, 這并不會引發錯誤, 但是這些名字是保留給將來使用的。
numeric
移除了 ASP 和 script PHP 標簽
使用類似 ASP 的標簽,以及 script 標簽來區分 PHP 代碼的方式被移除。 受到影響的標簽有:
被移除的 ASP 和 script 標簽
開標簽閉標簽
從不匹配的上下文發起調用
在不匹配的上下文中以靜態方式調用非靜態方法,?在 PHP 5.6 中已經廢棄, 但是在 PHP 7.0 中, 會導致被調用方法中未定義?$this?變量,以及此行為已經廢棄的警告。
class?A?{
public?function
test()?{?var_dump($this);?}
}
//?注意:并沒有從類?A?繼承
class?B?{
public?function
callNonStaticMethodOfA()?{?A::test();?}
}
(new
B)->callNonStaticMethodOfA();
?>
Output of the above example in PHP 5.6:
Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8
object(B)#1 (0) {
}
Output of the above example in PHP 7:
Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8
Notice: Undefined variable: this in /tmp/test.php on line 3
NULL
yield?變更為右聯接運算符
在使用?yield?關鍵字的時候,不再需要括號, 并且它變更為右聯接操作符,其運算符優先級介于?print?和?=>?之間。 這可能導致現有代碼的行為發生改變:
echo?yield?-1;
//?在之前版本中會被解釋為:
echo?(yield)?-?1;
//?現在,它將被解釋為:
echo?yield?(-1);
yield?$foo?or?die;
//?在之前版本中會被解釋為:
yield?($foo?or?die);
//?現在,它將被解釋為:
(yield?$foo)?or?die;
?>
可以通過使用括號來消除歧義。
函數定義不可以包含多個同名參數
在函數定義中,不可以包含兩個或多個同名的參數。 例如,下面代碼中的函數定義會觸發?E_COMPILE_ERROR?錯誤:
function?foo($a,?$b,?$unused,?$unused)?{
//
}
?>
Switch 語句不可以包含多個 default 塊
在 switch 語句中,兩個或者多個 default 塊的代碼已經不再被支持。 例如,下面代碼中的 switch 語句會觸發?E_COMPILE_ERROR?錯誤:
switch?(1)?{
default:
break;
default:
break;
}
?>
在函數中檢視參數值會返回?當前?的值
當在函數代碼中使用?func_get_arg()?或?func_get_args()?函數來檢視參數值, 或者使用?debug_backtrace()?函數查看回溯跟蹤, 以及在異常回溯中所報告的參數值是指參數當前的值(有可能是已經被函數內的代碼改變過的值), 而不再是參數被傳入函數時候的原始值了。
function?foo($x)?{
$x++;
var_dump(func_get_arg(0));
}
foo(1);?>
Output of the above example in PHP 5:
1
Output of the above example in PHP 7:
2
INI 文件中?#?注釋格式被移除
在 INI 文件中,不再支持以?#?開始的注釋行, 請使用?;(分號)來表示注釋。 此變更適用于?php.ini?以及用?parse_ini_file()?和?parse_ini_string()?函數來處理的文件。
JSON 擴展已經被 JSOND 取代
JSON 擴展已經被 JSOND 擴展取代。 對于數值的處理,有以下兩點需要注意的: 第一,數值不能以點號(.)結束 (例如,數值?34.?必須寫作?34.0?或?34)。 第二,如果使用科學計數法表示數值,e?前面必須不是點號(.) (例如,3.e3?必須寫作?3.0e3?或?3e3)。 另外,空字符串不再被視作有效的 JSON 字符串。
在數值溢出的時候,內部函數將會失敗
將浮點數轉換為整數的時候,如果浮點數值太大,導致無法以整數表達的情況下, 在之前的版本中,內部函數會直接將整數截斷,并不會引發錯誤。 在 PHP 7.0 中,如果發生這種情況,會引發 E_WARNING 錯誤,并且返回?NULL。
自定義會話處理器的返回值修復
在自定義會話處理器中,如果函數的返回值不是?FALSE,也不是?-1, 會引發致命錯誤。現在,如果這些函數的返回值不是布爾值,也不是?-1?或者?0,函數調用結果將被視為失敗,并且引發 E_WARNING 錯誤。
相等的元素在排序時的順序問題
由于內部排序算法進行了提升, 可能會導致對比時被視為相等的多個元素之間的順序不穩定。
Note:
在對比時被視為相等的多個元素之間的排序順序是不可信賴的,即使是相等的兩個元素, 他們的位置也可能被排序算法所改變。
錯誤的使用 break 和 switch 語句
在循環或者?switch?語句之外使用?break?和?continue?被視為編譯型錯誤(之前視為運行時錯誤),會引發?E_COMPILE_ERROR?錯誤。
Mhash 不再是一個單獨的擴展了
Mhash 擴展已經被完全整合進?Hash?擴展了。 因此,不要再使用?extension_loaded()?函數來檢測是否支持 MHash 擴展了, 建議使用?function_exists()?函數來進行檢測。 另外,函數?get_loaded_extensions()?以及相關的特性中,也不再報告 和 MHash 擴展相關的信息了。
declare(ticks)
declare(ticks)?指示符不再泄漏到不同的編譯單元中。
總結
以上是生活随笔為你收集整理的php7 php5.6 array,[转]php5.6 升级到php7及变化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java124 0,AcWing 124
- 下一篇: 离骚翻译及原文