PHP7 新增功能詳解(例項)

Shine-x發表於2019-03-21

PHP7速度是 PHP5.6 的兩倍

php7 最顯著的變化就是效能的極大提升,已接近Facebook開發的PHP執行引擎HHVM。在WordPress基準效能測試中,速度比5.6版本要快2~3倍,大大減少了記憶體佔用。PHP7在語言上也有一些變化,比如新增返回型別宣告、增加了一些新的保留關鍵字等。在安全方面,去除了PHP安全模式,新增魔術引號等。不僅如此,新版還支援64位,而且包含最新版Zend引擎。

測試一下

很簡單的一個例子,生成一個 60 萬元素的陣列,通過查詢key 的方式,來確定key是否存在。

<?php
$a = [];
for($i=0;$i<600000;$i++){
  $a[$i] = $i;
}
foreach($a as $item) {
 array_key_exists($item, $a);
}

我們分別在php5.6.11和php7.0.4來測試下效能。

php5.6.11

➜ time php 1.php
  0.67s user 0.06s system 67% cpu 1.078 total
➜ time php 1.php
  0.68s user 0.06s system 98% cpu 0.748 total
➜ time php 1.php
  0.65s user 0.06s system 67% cpu 1.052 total

三次平均下來,大致是 user使用 0.65秒,system使用0.06秒,67%的cpu率。總共1秒左右。

再看php7的情況

➜  time /usr/local/opt/php70/bin/php 1.php
  0.52s user 0.02s system 98% cpu 0.544 total
➜  time /usr/local/opt/php70/bin/php 1.php
  0.49s user 0.02s system 99% cpu 0.513 total
➜  time /usr/local/opt/php70/bin/php 1.php
  0.51s user 0.02s system 98% cpu 0.534 total

對比下來,user使用時間下降20%左右,system使用時間下降70%,cpu使用率更高高達98%。總體時間減少為。0.5秒。

這個例子看下來,效率提供了2倍。確實不錯。

再看一個例子。同樣也是生成一個 60 萬元素的陣列,查詢 value是否存在。

<?php
$a = [];
for($i=0;$i<600000;$i++){
    $a[$i] = $i;
}
foreach($a as $i) {
    array_search($i, $a);
}
?>

先看php5.6.11

➜  testPHP time php 2.php
0.68s user 0.03s system 66% cpu 1.077 total
➜  testPHP time php 2.php
0.68s user 0.02s system 98% cpu 0.710 total
➜  testPHP time php 2.php
0.68s user 0.02s system 98% cpu 0.713 total
➜  testPHP time php 2.php
0.69s user 0.02s system 98% cpu 0.721 total

再接著看php7.0.4

➜  testPHP time /usr/local/opt/php70/bin/php 2.php
0.12s user 0.02s system 69% cpu 0.201 total
➜  testPHP time /usr/local/opt/php70/bin/php 2.php
0.11s user 0.01s system 97% cpu 0.131 total
➜  testPHP time /usr/local/opt/php70/bin/php 2.php
0.11s user 0.01s system 96% cpu 0.130 total

明顯看出,快了6倍多。

1. 更多的標量型別宣告

現在php的標量有兩種模式: 強制 (預設) 和嚴格模式。 現在可以使用下列型別引數(無論用強制模式還是嚴格模式): 字串(string), 整數 (int), 浮點數 (float), 以及布林值 (bool)。它們擴充了PHP5中引入的其他型別:類名,介面,陣列和 回撥型別。在舊版中,函式的引數申明只能是(Array $arr)、(CLassName $obj)等,基本型別比如Int,String等是不能夠被申明的。

怎麼理解呢?php7之前的版本,我們要想限定一個函式的引數的型別,只有array或者class2種。

php7之前:

class MyInfo
{
    public $a = 123;
    public function getInfo(array $a, $b)
    {
        var_dump($a, $b);
    }
}
function getClass(MyInfo $a) {
    var_dump($a->a);
}
  • 我們想限定 getInfo的第一個引數,必須是陣列,所以,我們可以在引數$a前加一個array。來申明。
  • 同樣,我們想getClass的引數,必須是一個類,所以我們就用這個類的className字首來申明,起到強制使用的目的。

php7之前,只有這2種標量可以使用。

我們來使用一下:

$info = new MyInfo();
$info->getInfo([1,2,3,4], 4);

我們按照規定的來,第一個引數,傳陣列,結果當然是正常列印:

➜  testPHP php 3.php
array(3) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
}
int(4)

要是我們不按照規定來,就會報知名錯誤:

$info = new MyInfo();
$info->getInfo(122, 0);

報錯:

PHP Catchable fatal error:  Argument 1 passed to MyInfo::getInfo() must be of the type array, integer given, called in /Users/yangyi/www/testPHP/3.php on line 25 and defined in /Users/yangyi/www/testPHP/3.php on line 8
PHP Stack trace:
PHP   1. {main}() /Users/yangyi/www/testPHP/3.php:0
PHP   2. MyInfo->getInfo() /Users/yangyi/www/testPHP/3.php:25

使用類也一樣:

$info = new MyInfo();
getClass($info);

輸出結果:

➜  testPHP php 3.php
int(123)

同樣,我們傳入別的引數,就會報錯:

getClass(123);
➜  testPHP php 3.php
PHP Catchable fatal error:  Argument 1 passed to getClass() must be an instance of MyInfo, integer given, called in /Users/yangyi/www/testPHP/3.php on line 27 and defined in /Users/yangyi/www/testPHP/3.php on line 17
PHP Stack trace:
PHP   1. {main}() /Users/yangyi/www/testPHP/3.php:0
PHP   2. getClass() /Users/yangyi/www/testPHP/3.php:27

我們回到這次php7的升級,它擴充了標量的型別,增加了bool、int、string、float。

php7有2種兩種模式: 強制 和 嚴格模式。

強制模式

強制模式是預設模式,強制模式下,它會幫我們把數字型別的string型別,int整型,bool,強制型別。其他型別不能轉換,就會報錯。

還是剛才的例子:

class MyInfo
{
    public $a = 123;
    public function get1(bool $b)
    {
        var_dump($b);
    }
    public function get2(int $b)
    {
        var_dump($b);
    }
    public function get3(string $b)
    {
        var_dump($b);
    }
    public function get4(float $b)
    {
        var_dump($b);
    }
    public function get5(array $b)
    {
        var_dump($b);
    }
}

我們先全部傳入int 1

$info = new MyInfo();
$info->get1(1);
$info->get2(1);
$info->get3(1);
$info->get4(1);

看列印結果,它已經幫我們強制轉換了。

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:11:
bool(true)
/Users/yangyi/www/testPHP/3.php:19:
int(1)
/Users/yangyi/www/testPHP/3.php:26:
string(1) "1"
/Users/yangyi/www/testPHP/3.php:33:
double(1)

我們繼續,傳入 string 1.23 :

$info = new MyInfo();
$info->get1('1.23');
$info->get2('1.23');
$info->get3('1.23');
$info->get4('1.23');

看下,列印結果。也已經幫我們強制轉換了。

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:11:
bool(true)
/Users/yangyi/www/testPHP/3.php:19:
int(1)
/Users/yangyi/www/testPHP/3.php:26:
string(4) "1.23"
/Users/yangyi/www/testPHP/3.php:33:
double(1.23)

但是我們如果引數是array就沒法強制轉換,就會報錯了:

$info->get5('1.23');
 testPHP /usr/local/opt/php70/bin/php 3.php
PHP Fatal error:  Uncaught TypeError: Argument 1 passed to MyInfo::get5() must be of the type array, string given, called in /Users/yangyi/www/testPHP/3.php on line 54 and defined in /Users/yangyi/www/testPHP/3.php:37
我們在PHP5.6.11執行這些程式碼會報錯嗎?試一試:
$info = new MyInfo();
$info->get1('1.23');
$info->get2('1.23');
$info->get3('1.23');
$info->get4('1.23');
➜  testPHP php 3.php
PHP Catchable fatal error:  Argument 1 passed to MyInfo::get1() must be an instance of bool, string given, called in /Users/yangyi/www/testPHP/3.php on line 48 and defined in /Users/yangyi/www/testPHP/3.php on line 8

好吧。直接報錯了,雖然錯誤提示也是說型別錯誤,但是,其他是不支援這些型別的申明。

嚴格模式

前面說了,強制模式下,它會幫我們強制轉換,那麼嚴格模式下呢?

首先,如何開啟嚴格模式呢?

<?php
declare(strict_types=1);

加上就可以了,這樣,就進入嚴格模式,引數必須符合規定,不然報錯:

我們加上這句話,再執行下:

<?php
declare(strict_types=1);
...
...
$info = new MyInfo();
$info->get1('1.23');
$info->get2('1.23');
$info->get3('1.23');
$info->get4('1.23');

執行,看下結果,果然直接報錯了。

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to MyInfo::get1() must be of the type boolean, string given, called in /Users/yangyi/www/testPHP/3.php on line 49 and defined in /Users/yangyi/www/testPHP/3.php:9

2. 返回值型別宣告

  • 我們知道php的函式是沒有返回值型別的,return啥型別,就是啥型別。php7中增加了返回值型別,我們可以定義一個函式的返回值型別。
  • 和php7升級的標量型別宣告一樣,return的型別可以是以下這些:bool、int、string、float、array、class。

舉個例子來說,我們希望一個函式的返回值是一個陣列,我們可以這樣子書寫:

:array {}  // 冒號+返回型別
function returnInfo ($a) : array {
    return $a;
}
var_dump(returnInfo([1,2,3]));

是不是覺得很奇怪,又無可思議!!!

檢視列印結果:

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:64:
array(3) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
}

同樣,我們想返回是int整型:

function returnInfo ($a) : int {
    return $a;
}
var_dump(returnInfo('1.233'));

檢視結果,他已經幫我們強制轉換成整型了。

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:64:
int(1)

同樣,我們可以返回一個class型別的:

public function getLogger(): Logger {
    return $this->logger;
}

預設,也是強制模式,會幫我們轉換,如果,我們想使用嚴格模式,同樣是一樣的,在檔案頭部加上:

<?php
declare(strict_types=1);

就可以了,這樣,我們規定返回值是什麼型別,就必須得是這樣,不然就報致命報錯。

3. null合併運算子 (??)

由於日常使用中存在大量同時使用三元表示式和 isset()的情況, php7增加了一個新的語法糖 : null合併運算子 (??)

如果變數存在且值不為NULL, 它就會返回自身的值,否則返回它的第二個運算元。

//php version = 7
$username = $user ?? 'nobody';
//php  version < 7 得這樣使用:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

確實方便了很多。

我記得php5.3的更新中,加入了 三元運算子簡寫形式:

$a ?: $b

千萬別和??搞混淆了!!!

  • $a ?: $b的意思是 $a為true時,直接返回$a, 否則返回$b
  • $a ?? $b的意思是 $a isset($a)為true, 且不為NULL, 就返回$a, 否則返回$b。

看例子:

$user = 0;
$username = $user ?? 'nobody';
echo $username;  //輸出 0,因為 0 存在 且 不為NULL。
$username = $user ?: 'nobody';
echo $username; //輸出 'nobody',因為 0 為 false

4. 太空船操作符(組合比較符)

  • php7 中,新加入了一個比較符號:<=> ,因為長相像太空船,所以,也叫太空船操作符。
  • <=>用於比較兩個表示式。當$a小於、等於或大於$b時它分別返回-1、0或1。

看例子:

<?php
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>

其實,蠻多地方可以派上用場的。

5. 通過define()定義常量陣列

Array型別的常量現在可以通過 define()來定義。在 PHP5.6 中僅能通過const定義。

在php5.3中,增加了可以使用const來申明常量,替代define()函式,但是隻能申明一些簡單的變數。
舊式風格

define("XOOO", "Value");

新式風格

const XXOO = "Value";

const 形式僅適用於常量,不適用於執行時才能求值的表示式:

正確
const XXOO = 1234;
錯誤
const XXOO = 2 * 617;

在php5.6中,又對const進行來升級,可以支援上面的運算了。

const A = 2;
const B = A + 1;

但是,一隻都是在優化const,可是確把define()給搞忘記了,php 5.6申明一個陣列常量,只能用const。所以,在 php7 中把 define()申明一個陣列也給加上去了。

//php 7
define ('AWS' , [12,33,44,55]);
// php < 7
const QWE = [12,33,44,55];
echo AWS[1]; //12
echo QWE[2]; //33

至此,到php7版本,define()的功能和const就一摸一樣了,所以,你隨便用哪一個都可以,但是因為在class類中,什麼常量是const。所以,我們就統一用const申明常量好了。

6. 匿名類

現在已經支援通過new class 來例項化一個匿名類,這可以用來替代一些用後即焚的完整類定義。

看下這個官方文件上的一個栗子:

<?php
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());
?>

我們先輸出的列印的結果,顯示為匿名類:

class class@anonymous#2 (0) {
}

我們來分解下,還原被偷懶的少寫的程式碼:

class logClass implements Logger {
    public function log(string $msg) {
        echo $msg;
    }
}
$app = new Application;
$log2 = new logClass;
$app->setLogger($log2);

輸出結果為:

class logClass#2 (0) {
}

雖然程式碼簡潔了很多,但是還是有點不適應,多用用就好了。

還記得php中的匿名函式嘛?在php5.3中新增的匿名函式,結合新的,順便複習下:

function arraysSum(array ...$arrays): array {
    return array_map(function(array $array): int {
        return array_sum($array);
    }, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));

輸出結果為:

Array
(
    [0] => 6
    [1] => 15
    [2] => 24
)

7. Unicode codepoint 轉譯語法

ps : 由於用的少,我就直接抄官網的說明了。

這接受一個以16進位制形式的 Unicode codepoint,並列印出一個雙引號或heredoc包圍的 UTF-8 編碼格式的字串。 可以接受任何有效的 codepoint,並且開頭的 0 是可以省略的。

echo "\u{0000aa}";
echo "\u{aa}"; //省略了開頭的0
echo "\u{9999}";

看下輸出:

我們在php5.6環境下執行下呢?會怎樣:

\u{aa} \u{0000aa} \u{9999}

好吧,直接原樣輸出了。

8. Closure::call() 閉包

ps : 由於用的少,我就直接抄官網的說明了。

Closure::call() 現在有著更好的效能,簡短幹練的暫時繫結一個方法到物件上閉包並呼叫它。

<?php
class A {private $x = 1;}
// php 7之前:
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
echo $getX();
// PHP 7:
$getX = function() {return $this->x;};
echo $getX->call(new A);

會輸出:

1
1

9. 為unserialize()提供過濾

unserialize 這個函式應該不陌生,它是php中用解開用serialize序列化的變數。

看個栗子:

<?php
$a = [1,2,3,4,5,6];
$b = serialize($a);
$c = unserialize($b);
var_dump($a, $b, $c);

列印結果為:

array(6) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
  [3] =>
  int(4)
  [4] =>
  int(5)
  [5] =>
  int(6)
}
string(54) "a:6:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;}"
array(6) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
  [3] =>
  int(4)
  [4] =>
  int(5)
  [5] =>
  int(6)
}

現在php7中unserialize會變得更佳好用,它多了一個引數,用來反序列化包涵class的過濾不需要的類,變的更加安全。

  • unserialize($one, ["allowed_classes" => true]);
  • unserialize($one, ["allowed_classes" => false]);
  • unserialize($one, ["allowed_classes" => [class1,class2,class3]]);
    舉個例子,先序列化一個類。
    class MyInfo {
    public function getMyName()
    {
    return 'phper';
    }
    }
    $phper = new MyInfo();
    $one = serialize($phper);
    //引數allowed_classes 設定為 true,表示允許解析class
    $two = unserialize($one, ["allowed_classes" => true]);
    //引數allowed_classes 設定為 false,表示不允許解析class
    $three = unserialize($one, ["allowed_classes" => false]);
    //不加引數。正常解析。
    $four = unserialize($one);
    //只允許解析 類 MyInfo1。
    $five = unserialize($one, ["allowed_classes" => ["MyInfo1"]]);
    //分別輸出下 getMyName方法;
    var_dump($one);
    var_dump($two->getMyName());
    var_dump($three->getMyName());
    var_dump($four->getMyName());
    var_dump($five->getMyName());

    發現3和5直接報致命錯誤了:

    PHP Fatal error:  main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "MyInfo" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition  in /Users/yangyi/www/php7/5.php on line 22
    大致意思就是,沒許可權解析。

所以,我們改一下:

$three = unserialize($one, ["allowed_classes" => true]);
$five = unserialize($one, ["allowed_classes" => ["MyInfo"]]);

再輸出,就正常了。

/Users/yangyi/www/php7/5.php:22:
string(17) "O:6:"MyInfo":0:{}"
/Users/yangyi/www/php7/5.php:23:
string(5) "phper"
/Users/yangyi/www/php7/5.php:24:
string(5) "phper"
/Users/yangyi/www/php7/5.php:25:
string(5) "phper"
/Users/yangyi/www/php7/5.php:26:
string(5) "phper"

發現我目前為止並沒用到,並沒有什麼亂用,好吧,繼續下一個。

10. IntlChar

ps : 由於用的少,我就直接抄官網的說明了。

新增加的 IntlChar(http://php.net/manual/zh/class.intlchar.ph...) 類旨在暴露出更多的 ICU 功能。這個類自身定義了許多靜態方法用於操作多字符集的 unicode 字元。

<?php
printf('%x', IntlChar::CODEPOINT_MAX);
echo IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));

以上例程會輸出:

10ffff
COMMERCIAL AT
bool(true)

若要使用此類,請先安裝Intl擴充套件。

1.廢棄擴充套件

Ereg 正規表示式 

  • mssql 
  • mysql 
  • sybase_ct

2.廢棄的特性

  • 不能使用同名的建構函式 
  • 例項方法不能用靜態方法的方式呼叫

3.廢棄的函式

方法呼叫 

  • call_user_method() 
  • call_user_method_array()

應該採用

  • call_user_func()
  • call_user_func_array()

加密相關函式

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

注意: PHP7.1 以後mcrypt_*序列函式都將被移除。推薦使用:openssl 序列函式

雜項

  • set_magic_quotes_runtime 
  • set_socket_blocking 
  • Split 
  • imagepsbbox() 
  • imagepsencodefont() 
  • imagepsextendfont() 
  • imagepsfreefont() 
  • imagepsloadfont() 
  • imagepsslantfont() 
  • imagepstext()

4.廢棄的用法

  • $HTTP_RAW_POST_DATA 變數被移除, 使用php://input來代
  • ini檔案裡面不再支援#開頭的註釋, 使用”;”
  • 移除了ASP格式的支援和指令碼語法的支援:<%< script language=php >

1.字串處理機制修改

含有十六進位制字元的字串不再視為數字, 也不再區別對待.

var_dump("0x123" == "291"); // false
var_dump(is_numeric("0x123")); // false
var_dump("0xe" + "0x1"); // 0
var_dump(substr("f00", "0x1")) // foo

2.整型處理機制修改

Int64支援, 統一不同平臺下的整型長度, 字串和檔案上傳都支援大於2GB. 64位PHP7字串長度可以超過2^31次方位元組.

// 無效的八進位制數字(包含大於7的數字)會報編譯錯誤
$i = 0681; // 老版本php會把無效數字忽略。
// 位移負的位置會產生異常
var_dump(1 >> -1);
// 左位移超出位數則返回0
var_dump(1 << 64);// 0 
// 右位移超出會返回0或者-1
var_dump(100 >> 32);// 0 
var_dump(-100 >> 32);// -1 

3.引數處理機制修改

不支援重複引數命名

function func(a,a,b, c,c,c) {} ;//hui報錯

func_get_arg()func_get_args()這兩個方法返回引數當前的值, 而不是傳入時的值, 當前的值有可能會被修改

所以需要注意,在函式第一行最好就給記錄下來,否則後續有修改的話,再讀取就不是傳進來的初始值了。

function foo($x) {
    $x++;
    echo func_get_arg(0);
}
foo(1); //返回2


## 4.foreach修改

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

$arr = [1,2,3];
foreach ($arr as &$val) {
    echo current($arr);// php7 全返回0
}


按照值進行迴圈的時候, 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不行)

## 5. 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];r;

list()現在也適用於陣列物件

list($a, $b) = (object)new ArrayObject([0, 1]);


## 6.變數處理機制修改
> 對變數、屬性和方法的間接呼叫現在將嚴格遵循從左到右的順序來解析,而不是之前的混雜著幾個特殊案例的情況。

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

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


## 7.雜項
* debug_zval_dump() 現在列印 “int” 替代 “long”, 列印 “float” 替代 “double”
* dirname() 增加了可選的第二個引數, depth, 獲取當前目錄向上 depth 級父目錄的名稱。
* getrusage() 現在支援 Windows.mktime() and gmmktime() 函式不再接受 is_dst 引數。
* preg_replace() 函式不再支援 “\e” (PREG_REPLACE_EVAL). 應當使用 preg_replace_callback() 替代。
* setlocale() 函式不再接受 category 傳入字串。 應當使用 LC_* 常量。
* exec(), system() and passthru() 函式對 NULL 增加了保護.
* shmop_open() 現在返回一個資源而非一個int, 這個資源可以傳給shmop_size(), shmop_write(), shmop_read(), shmop_close() 和 shmop_delete().
* 為了避免記憶體洩露,xml_set_object() 現在在執行結束時需要手動清除 $parse。
* curl_setopt 設定項CURLOPT_SAFE_UPLOAD變更
* TRUE 禁用 @ 字首在 CURLOPT_POSTFIELDS 中傳送檔案。 意味著 @ 可以在欄位中安全得使用了。 可使用 CURLFile作為上傳的代替。 
* PHP 5.5.0 中新增,預設值 FALSE。 PHP 5.6.0 改預設值為 TRUE。. PHP 7 刪除了此選項, 必須使用 CURLFile interface 來上傳檔案。
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章