1. 程式人生 > >PHP7不向下相容部分

PHP7不向下相容部分

PHP7不向下相容部分

本文主要目標版本是7.1。

1. 型別宣告

PHP7下要求函式實參型別與聲明瞭型別的形參型別一致。
可以使用字串(string), 整數 (int), 浮點數 (float), 以及布林值 (bool),陣列(array),來宣告函式的引數型別與函式返回值。

function s(string $a, array $b, int $c, float $d) {
    echo "str a=$a c+d=".($c*$d).";\n";
}
s([], [], 2, 3.8);//Fatal error: Uncaught TypeError: Argument 1 passed to s() must be of the type string, array given
s(1.4, [], 2, 3.8);//str a=1.4 c+d=7.6; s('a2', '', 2, 3.8);//Fatal error: Uncaught TypeError: Argument 2 passed to s() must be of the type array, string given s('a3', [], [], 3.8);//Fatal error: Uncaught TypeError: Argument 3 passed to s() must be of the type integer, array given s('a4', [], '', 3.8);//Fatal error: Uncaught TypeError: Argument 3 passed to s() must be of the type integer, string given
s('a5', [], 2, []);//Fatal error: Uncaught TypeError: Argument 4 passed to s() must be of the type float, array given s('a6', [], 2, '');//Fatal error: Uncaught TypeError: Argument 4 passed to s() must be of the type float, string given s('a7', [], 2.9, 3.8);//str a=a7 c+d=7.6;//2.9被當做整形2處理

使用嚴格模式:declare(strict_types=1);

declare(strict_types=1);
function add(int $a, int $b): int {
    return $a+$b;
}
echo add(1, 2);
echo add(1.9, 2.6);

php5是無法執行上面程式碼的,php7執行的時候會先輸出一個3和一個報錯( Argument 1 passed to add() must be of the type integer, float given);
標量型別宣告 有兩種模式: 強制 (預設) 和 嚴格模式。
declare(strict_types=1),必須放在檔案的第一行執行程式碼,當前檔案有效!
每個檔案宣告declare(strict_types=1)不是個理想的解決辦法。

使用phan可以掃描出以上錯誤。

必須手動檢查和修改。
int<->float不會fatal,但是會位數損失。int|flot<->string|array會fatal。

grep -w int -rn ./ -rn | grep -w function | grep -v -e .git -e .js -e .html -e '@' -e .as | less

array使用很多:

grep -w array -rn ./ -rn | grep -w function | grep -v -e .git -e .js -e .html -e '@' -e .as -e 'array()' | less

float,double,string,bool使用無。
從phan的掃描結果中檢查。

2. 型別聲明後跨型別使用

PHP7下申明物件後,將物件當成另一種型別使用會報出Fatal錯誤。主要在array型別。
錯誤用法如下:

$wheres = '';
$wheres[] = ' 1 and aStatus=1';

以下用法是容忍的,會Notice或Warning,不會Fatal:

$a = 'a';
$a = 1; 
$a = $a[1];// 返回空
$a = [3];
$a++;// 對陣列++無效

必須手動檢查和修改。

grep -w int -rn ./ -rn | grep -w function | grep -v -e .git -e .js -e .html -e '@' | less

可以從phan的掃描結果中檢查。

3. 函式限制

PHP7不能使用同名的建構函式
PHP7例項方法不能用靜態方法的方式呼叫
PHP7函式引數個數,呼叫的個數不滿足宣告的格式,會觸發Fatal

function s(string $a, array $b) {
    echo "str a=$a;\n";
}
s(1);

//Uncaught ArgumentCountError: Too few arguments to function s()

需要手動檢查。
從phan的掃描結果中檢查。

4. 不相容函式

4.1 mcrypt_系列被移除

mcrypt_generic_end()
mcrypt_ecb()
mcrypt_cbc()
mcrypt_cfb()
mcrypt_ofb()

搜尋: mcrypt_*

grep mcrypt_ -rn ./ -rn | grep -v -e .git -e .js -e .html -e '@' -e .as | less

使用openssh系列替換。

4.2 set_exception_handler() 不再保證收到的一定是 Exception 物件

PHP5下原型是:
set_exception_handler(function (Exception $e) {…})
PHP7下原型是:
set_exception_handler(function (Throwable $e) {…})

4.3 set_magic_quotes_runtime 被移除

4.4 set_socket_blocking 被移除

\libraries\PHPExcel\Shared\PCLZip\pclzip.lib.php
\libraries\PHPMailer\Client.php

4.5 split 被移除

4.6 imageps* 被移除

imagepsbbox()
imagepsencodefont()
imagepsextendfont()
imagepsfreefont()
imagepsloadfont()
imagepsslantfont()
imagepstext()

4.7 mktime()引數變化

mktime() gmmktime() 不再接受$is_dst引數

4.8 shmop_函式返回變化

shmop_open() The return type of shmop_open() has been changed from int to resource.

4.9 setlocale() 函式

不再接受 category 傳入字串。 應當使用 LC_* 常量。

4.10 xml_set_object

為了避免記憶體洩露,xml_set_object() 現在在執行結束時需要手動清除 $parse。

4.11 curl_setopt

curl_setopt 設定項CURLOPT_SAFE_UPLOAD變更:
TRUE 禁用 @ 字首在 CURLOPT_POSTFIELDS 中傳送檔案。 意味著 @ 可以在欄位中安全得使用了。 可使用 CURLFile作為上傳的代替。
PHP 5.5.0 中新增,預設值 FALSE。 PHP 5.6.0 改預設值為 TRUE。. PHP 7 刪除了此選項, 必須使用 CURLFile interface 來上傳檔案。
curl_setopt 中CURLOPT_HTTPHEADER變更:
值必須是array,否則會出發warning

4.12 preg_函式變化

preg_replace() 函式不再支援 “\e” (PREG_REPLACE_EVAL). 應當使用 preg_replace_callback() 替代。

需要手動檢查。

for file in `grep -w 'preg_replace' -rn * | grep -v -e '.js:' -e '.html:' -e '.css:'  |awk -F ':' '{print $1}' | sort | uniq`; do echo grep "$file"; grep '/e' "$file" -n ; done

4.13 Eval option for mb_ereg_replace() and mb_eregi_replace()

4.14 xml_parser_free

xml_parser_free() is no longer sufficient to free the parser resource, if it references an object and this object references that parser resource. In this case it is necessary to additionally unset the $parser.

這個函式不能滿足釋放xml parser資源,需要用unset($parser)方法。

grep 'xml_parser_free' -rn ./ -rn | grep -v -e .git -e .js -e .html -e '@' -e .as | less

5 HTTP_RAW_POST_DATA

HTTP_RAW_POST_DATA替代為file_get_contents(‘php://input’)

grep -w HTTP_RAW_POST_DATA -rn ./ -rn | grep -v -e .git -e .js -e .html -e '@' -e .as | less

詳細可參考:
http://www.nowamagic.net/academy/detail/12220520

6 foreach 修改

foreach()迴圈對陣列內部指標不再起作用

$arr = [1,2,3];
foreach ($arr as &$val) {
    echo current($arr);// php7 全返回0
}
for i in `grep -w current -rn ./ -rn | grep -v -e .git -e .js -e .html -e '@' -e .as | grep 'current  (' | awk -F ':' '{print $1}' | sort | uniq `; do echo $i; grep  'foreach.*&' $i -n ; done

按照值進行迴圈的時候, foreach是對該陣列的拷貝操作

$arr = [1,2,3];
foreach ($arr as $val) {
    unset($arr[1]);
}
var_dump($arr);
//最新的php7依舊會打印出[1,2,3]。(ps:7.0.0不行) 老的會打印出[1,3]

按照引用進行迴圈的時候, 對陣列的修改會影響迴圈

$arr = [1];
foreach ($arr as $val) {
    var_dump($val);
    $arr[1]=2;
}
//最新的php7依舊會追加新增元素的迴圈。(ps:7.0.0不行)

7 list修改

不再按照相反的順序賦值

//$arr將會是[1,2,3]而不是之前的[3,2,1]
list($arr[], $arr[], $arr[]) = [1,2,3];

不再支援字串拆分功能。

// $x = null 並且 $y = null
$str = 'xy';
list($x, $y) = $str;

空的list()賦值不再允許,手動檢查。

list() = [123];//php7不允許
grep 'list(' -rn ./ -rn | grep -v -e .git -e .js -e .html -e '@' -e .as | grep -w list | less

8 變數語法處理機制修改

對變數、屬性和方法的間接呼叫現在將嚴格遵循從左到右的順序來解析,而不是之前的混雜著幾個特殊案例的情況。 下面這張表說明了這個解析順序的變化。

引用賦值時自動建立的陣列元素或者物件屬性順序和以前不同了

$arr = [];
$arr['a'] = &$arr['b'];
$arr['b'] = 1;
// php7: ['a' => 1, 'b' => 1]
// php5: ['b' => 1, 'a' => 1]

需要手動檢查。

9 其他

  • 移除了ASP格式的支援和指令碼語法的支援: <% 和 < script language=php >
  • 不支援重複引數命名

需要手動檢查。

參考:

本文目標版本是7.1,更高版本要繼續參考官方: