PHP特性整合(PHP5.X到PHP7.1.x)

風來了發表於2016-10-01

PHP7 已經出來1年了,PHP7.1也即將和大家見面,這麼多好的特性,好的方法,為什麼不使用呢,也希望PHP越來越好。
在這裡整理 PHP 5.1 ,PHP5.2,PHP5.3,PHP5.4,PHP5.5,PHP5.6 ,PHP7,PHP7.1 所有新特性,已備大家學習及使用
PHP5.1~PHP5.6 http://blog.csdn.net/fenglailea/article/details/9853645
PHP7~PHP7.1
http://blog.csdn.net/fenglailea/article/details/52717364
風.fox

Buid-in web server內建了一個簡單的Web伺服器

把當前目錄作為Root Document只需要這條命令即可:

php -S localhost:3300

也可以指定其它路徑

php -S localhost:3300 -t /path/to/root  

還可以指定路由

php -S localhost:3300 router.php

名稱空間(php5.3)

名稱空間的分隔符為反斜杆

namespace foxlanmpsTable;    
class Select {}

獲取完整類別名稱

PHP5.3 中引入名稱空間的別名類和名稱空間短版本的功能。雖然這並不適用於字串類名稱

use SomeDeeplyNestedNamespaceFooBar;    
// does not work, because this will try to use the global `FooBar` class    
$reflection = new ReflectionClass(`FooBar`);   
echo FooBar::class;  

為了解決這個問題採用新的FooBar::class語法,它返回類的完整類別名稱

名稱空間 use 操作符開始支援函式和常量的匯入

namespace NameSpace {  
    const FOO = 42;  
    function f() { echo __FUNCTION__."
"; }  
}  
namespace {  
    use const NameSpaceFOO;  
    use function NameSpacef;  

    echo FOO."
";  
    f();  
} 

輸出
42
NameSpacef

Group use declarations

從同一 namespace 匯入的類、函式和常量現在可以通過單個 use 語句 一次性匯入了。

//PHP7之前
use somenamespaceClassA;
use somenamespaceClassB;
use somenamespaceClassC as C;
use function somenamespacefn_a;
use function somenamespacefn_b;
use function somenamespacefn_c;
use const somenamespaceConstA;
use const somenamespaceConstB;
use const somenamespaceConstC;

// PHP7之後
use somenamespace{ClassA, ClassB, ClassC as C};
use function somenamespace{fn_a, fn_b, fn_c};
use const somenamespace{ConstA, ConstB, ConstC};

支援延遲靜態繫結

static關鍵字來引用當前類,即實現了延遲靜態繫結

class A {    
    public static function who() {    
        echo __CLASS__;    
    }    
    public static function test() {    
        static::who(); // 這裡實現了延遲的靜態繫結    
    }    
}    
class B extends A {    
    public static function who() {    
         echo __CLASS__;    
    }    
}
B::test();    

輸出結果:
B

支援goto語句

多數計算機程式設計語言中都支援無條件轉向語句goto,當程式執行到goto語句時,即轉向由goto語句中的標號指出的程式位置繼續執行。儘管goto語句有可能會導致程式流程不清晰,可讀性減弱,但在某些情況下具有其獨特的方便之處,例如中斷深度巢狀的迴圈和 if 語句。

goto a;    
echo `Foo`;    
a:    
echo `Bar`;    
for($i=0,$j=50; $i<100; $i++) {    
  while($j--) {    
    if($j==17) goto end;    
  }     
}    
echo "i = $i";    
end:    
echo `j hit 17`; 

支援閉包、Lambda/Anonymous函式

閉包(Closure)函式和Lambda函式的概念來自於函式程式設計領域。例如JavaScript 是支援閉包和 lambda 函式的最常見語言之一。
在PHP中,我們也可以通過create_function()在程式碼執行時建立函式。但有一個問題:建立的函式僅在執行時才被編譯,而不與其它程式碼同時被編譯成執行碼,因此我們無法使用類似APC這樣的執行碼快取來提高程式碼執行效率。
在PHP5.3中,我們可以使用Lambda/匿名函式來定義一些臨時使用(即用即棄型)的函式,以作為array_map()/array_walk()等函式的回撥函式。

echo preg_replace_callback(`~-([a-z])~`, function ($match) {    
    return strtoupper($match[1]);    
}, `hello-world`);    
// 輸出 helloWorld    
$greet = function($name)    
{    
    printf("Hello %s
", $name);    
};    
$greet(`World`);    
$greet(`PHP`);    
//...在某個類中    
$callback =      function ($quantity, $product) use ($tax, &$total)         {    
   $pricePerItem = constant(__CLASS__ . "::PRICE_" .  strtoupper($product));    
   $total += ($pricePerItem * $quantity) * ($tax + 1.0);    
 };    

魔術方法__callStatic()和__invoke()

PHP中原本有一個魔術方法__call(),當程式碼呼叫物件的某個不存在的方法時該魔術方法會被自動呼叫。新增的__callStatic()方法則只用於靜態類方法。當嘗試呼叫類中不存在的靜態方法時,__callStatic()魔術方法將被自動呼叫。

class MethodTest {    
    public function __call($name, $arguments) {    
        // 引數 $name 大小寫敏感    
        echo "呼叫物件方法 `$name` "    
             . implode(` -- `, $arguments). "
";    
    }    
    /**  PHP 5.3.0 以上版本中本類方法有效  */    
    public static function __callStatic($name, $arguments) {    
        // 引數 $name 大小寫敏感    
        echo "呼叫靜態方法 `$name` "    
             . implode(` -- `, $arguments). "
";    
    }    
}    

$obj = new MethodTest;    
$obj->runTest(`通過物件呼叫`);    
MethodTest::runTest(`靜態呼叫`);  // As of PHP 5.3.0

以上程式碼執行後輸出如下:
呼叫物件方法’runTest’ –- 通過物件呼叫呼叫靜態方法’runTest’ –- 靜態呼叫
以函式形式來呼叫物件時,__invoke()方法將被自動呼叫。

class MethodTest {    
    public function __call($name, $arguments) {    
        // 引數 $name 大小寫敏感    
        echo "Calling object method `$name` "    
             . implode(`, `, $arguments). "
";    
    }    

    /**  PHP 5.3.0 以上版本中本類方法有效  */    
    public static function __callStatic($name, $arguments) {    
        // 引數 $name 大小寫敏感    
        echo "Calling static method `$name` "    
             . implode(`, `, $arguments). "
";    
    }    
}    
$obj = new MethodTest;    
$obj->runTest(`in object context`);    
MethodTest::runTest(`in static context`);  // As of PHP 5.3.0  

Nowdoc語法

用法和Heredoc類似,但使用單引號。Heredoc則需要通過使用雙引號來宣告。
Nowdoc中不會做任何變數解析,非常適合於傳遞一段PHP程式碼。

// Nowdoc 單引號 PHP 5.3之後支援    
$name = `MyName`;    
echo <<<`EOT`    
My name is "$name".    
EOT;    
//上面程式碼輸出 My name is "$name". ((其中變數不被解析)    
// Heredoc不加引號    
echo <<<FOOBAR    
Hello World!    
FOOBAR;    
//或者 雙引號 PHP 5.3之後支援    
echo <<<"FOOBAR"    
Hello World!    
FOOBAR;  

支援通過Heredoc來初始化靜態變數、類成員和類常量。

// 靜態變數    
function foo()    
{    
    static $bar = <<<LABEL    
Nothing in here...    
LABEL;    
}    
// 類成員、常量    
class foo    
{    
    const BAR = <<<FOOBAR    
Constant example    
FOOBAR;    

    public $baz = <<<FOOBAR    
Property example    
FOOBAR;    
}  

在類外也可使用const來定義常量

//PHP中定義常量通常是用這種方式  
define("CONSTANT", "Hello world.");  

//並且新增了一種常量定義方式  
const CONSTANT = `Hello World`; 

三元運算子增加了一個快捷書寫方式

原本格式為是(expr1) ? (expr2) : (expr3)
如果expr1結果為True,則返回expr2的結果。
新增一種書寫方式,可以省略中間部分,書寫為expr1 ?: expr3
如果expr1結果為True,則返回expr1的結果

$expr1=1;
$expr2=2;
//原格式  
$expr=$expr1?$expr1:$expr2  
//新格式  
$expr=$expr1?:$expr2

輸出結果:
1
1

空合併運算子(??)

簡化判斷

$param = $_GET[`param`] ?? 1;

相當於:

$param = isset($_GET[`param`]) ? $_GET[`param`] : 1;

Json更懂中文(JSON_UNESCAPED_UNICODE)

echo json_encode("中文", JSON_UNESCAPED_UNICODE);  
//輸出:"中文" 

二進位制

$bin  = 0b1101;  
echo $bin;  
//13 

Unicode codepoint 轉譯語法

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

 echo "u{9876}"

舊版輸出:u{9876}
新版輸入:頂

使用 ** 進行冪運算

加入右連線運算子 * 來進行冪運算。 同時還支援簡寫的 *= 運算子,表示進行冪運算並賦值。

printf("2 ** 3 ==      %d
", 2 ** 3);
printf("2 ** 3 ** 2 == %d
", 2 ** 3 ** 2);

$a = 2;
$a **= 3;
printf("a ==           %d
", $a);

輸出
2 ** 3 == 8
2 * 3 * 2 == 512
a == 8

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

太空船操作符用於比較兩個表示式。當 ab 時它分別返回 -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

Traits

Traits提供了一種靈活的程式碼重用機制,即不像interface一樣只能定義方法但不能實現,又不能像class一樣只能單繼承。至於在實踐中怎樣使用,還需要深入思考。
魔術常量為TRAIT

官網的一個例子:  
trait SayWorld {  
        public function sayHello() {  
                parent::sayHello();  
                echo "World!
";  
                echo `ID:` . $this->id . "
";  
        }  
}  

class Base {  
        public function sayHello() {  
                echo `Hello `;  
        }  
}  

class MyHelloWorld extends Base {  
        private $id;  

        public function __construct() {  
                $this->id = 123456;  
        }  

        use SayWorld;  
}  

$o = new MyHelloWorld();  
$o->sayHello();  

/*will output: 
Hello World! 
ID:123456 
 */  

array 陣列簡寫語法

$arr = [1,`james`, `james@fwso.cn`];  
$array = [  
  "foo" => "bar",  
  "bar" => "foo"  
  ]; 

array 陣列中某個索引值簡寫

function myfunc() {  
    return array(1,`james`, `james@fwso.cn`);  
}
echo myfunc()[1];  

$name = explode(",", "Laruence,male")[0];  
explode(",", "Laruence,male")[3] = "phper";  

非變數array和string也能支援下標獲取了

echo array(1, 2, 3)[0];  
echo [1, 2, 3][0];  
echo "foobar"[2];  

支援為負的字串偏移量

現在所有接偏移量的內建的基於字串的函式都支援接受負數作為偏移量,包括陣列解引用操作符([]).

var_dump("abcdef"[-2]);
var_dump(strpos("aabbcc", "b", -3));

以上例程會輸出:

string (1) "e"
int(3)

常量引用

“常量引用”意味著陣列可以直接操作字串和陣列字面值。舉兩個例子:

function randomHexString($length) {    
    $str = ``;    
    for ($i = 0; $i < $length; ++$i) {    
        $str .= "0123456789abcdef"[mt_rand(0, 15)]; // direct dereference of string    
    }    
}    
function randomBool() {    
    return [false, true][mt_rand(0, 1)]; // direct dereference of array    
}   

常量增強

允許常量計算,允許使用包含數字、字串字面值和常量的標量表示式

const A = 2;  
const B = A + 1;  
class C  
{  
    const STR = "hello";  
    const STR2 = self::STR + ", world";  
}

允許常量作為函式引數預設

function test($arg = C::STR2)

類常量可見性
現在起支援設定類常量的可見性。

class ConstDemo
{
    const PUBLIC_CONST_A = 1;
    public const PUBLIC_CONST_B = 2;
    protected const PROTECTED_CONST = 3;
    private const PRIVATE_CONST = 4;
}

通過define()定義常量陣列

define(`ANIMALS`, [`dog`, `cat`, `bird`]);
echo ANIMALS[1]; // outputs "cat"

函式變數型別宣告

兩種模式 : 強制 ( 預設 ) 和 嚴格模式
型別:array,object(物件),string、int、float和 bool

class bar {  
function foo(bar $foo) {  
}  
//其中函式foo中的引數規定了傳入的引數必須為bar類的例項,否則系統會判斷出錯。同樣對於陣列來說,也可以進行判斷,比如:  
function foo(array $foo) {  
}  
}  
  foo(array(1, 2, 3)); // 正確,因為傳入的是陣列  
  foo(123); // 不正確,傳入的不是陣列

function add(int $a) 
{ 
    return 1+$a; 
} 
var_dump(add(2));

function foo(int $i) { ... }  
foo(1);      // $i = 1  
foo(1.0);    // $i = 1  
foo("1");    // $i = 1  
foo("1abc"); // not yet clear, maybe $i = 1 with notice  
foo(1.5);    // not yet clear, maybe $i = 1 with notice  
foo([]);     // error  
foo("abc");  // error  

引數跳躍

如果你有一個函式接受多個可選的引數,目前沒有辦法只改變最後一個引數,而讓其他所有引數為預設值。
RFC上的例子,如果你有一個函式如下:

function create_query($where, $order_by, $join_type=``, $execute = false, $report_errors = true) { ... }  

那麼有沒有辦法設定$report_errors=false,而其他兩個為預設值。為了解決這個跳躍引數的問題而提出:

create_query("deleted=0", "name", default, default, false);  

可變函式引數

代替 func_get_args()

function add(...$args)  
{  
    $result = 0;  
    foreach($args as $arg)  
        $result += $arg;  
    return $result;  
} 

可為空(Nullable)型別

型別現在允許為空,當啟用這個特性時,傳入的引數或者函式返回的結果要麼是給定的型別,要麼是 null 。可以通過在型別前面加上一個問號來使之成為可為空的。

function test(?string $name)
{
    var_dump($name);
}

以上例程會輸出:

string(5) "tpunt"
NULL
Uncaught Error: Too few arguments to function test(), 0 passed in...

Void 函式

在PHP 7 中引入的其他返回值型別的基礎上,一個新的返回值型別void被引入。 返回值宣告為 void 型別的方法要麼乾脆省去 return 語句,要麼使用一個空的 return 語句。 對於 void 函式來說,null 不是一個合法的返回值。

function swap(&$left, &$right) : void
{
    if ($left === $right) {
        return;
    }
    $tmp = $left;
    $left = $right;
    $right = $tmp;
}
$a = 1;
$b = 2;
var_dump(swap($a, $b), $a, $b);

以上例程會輸出:

null
int(2)
int(1)

試圖去獲取一個 void 方法的返回值會得到 null ,並且不會產生任何警告。這麼做的原因是不想影響更高層次的方法。

返回值型別宣告

函式和匿名函式都可以指定返回值的型別

function show(): array 
{ 
    return [1,2,3,4]; 
}

function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}

引數解包功能

在呼叫函式的時候,通過 … 操作符可以把陣列或者可遍歷物件解包到引數列表,這和Ruby等語言中的擴張(splat)操作符類似

function add($a, $b, $c) {  
    return $a + $b + $c;  
}  
$arr = [2, 3];  
add(1, ...$arr);

例項化類

class test{  
    function show(){  
return `test`;  
    }  
}  
echo (new test())->show();

支援 Class::{expr}() 語法

foreach ([new Human("Gonzalo"), new Human("Peter")] as $human) {  
    echo $human->{`hello`}();  
} 

Callable typehint

function foo(callable $callback) {  
}

foo("false"); //錯誤,因為false不是callable型別  
  foo("printf"); //正確  
  foo(function(){}); //正確  
class A {  
  static function show() {  
    }  
}  
  foo(array("A", "show")); //正確

Getter 和 Setter

如果你從不喜歡寫這些getXYZ()和setXYZ($value)方法,那麼這應該是你最受歡迎的改變。提議新增一個新的語法來定義一個屬性的設定/讀取:

class TimePeriod {  
    public $seconds;  
    public $hours {  
        get { return $this->seconds / 3600; }  
        set { $this->seconds = $value * 3600; }  
    }  
}  
$timePeriod = new TimePeriod;  
$timePeriod->hours = 10;  
var_dump($timePeriod->seconds); // int(36000)  
var_dump($timePeriod->hours);   // int(10)  

迭代器 yield

目前,自定義迭代器很少使用,因為它們的實現,需要大量的樣板程式碼。生成器解決這個問題,並提供了一種簡單的樣板程式碼來建立迭代器。
例如,你可以定義一個範圍函式作為迭代器:

function *xrange($start, $end, $step = 1) {  
    for ($i = $start; $i < $end; $i += $step) {  
        yield $i;  
    }  
}  
foreach (xrange(10, 20) as $i) {  
    // ...  
}  

上述xrange函式具有與內建函式相同的行為,但有一點區別:不是返回一個陣列的所有值,而是返回一個迭代器動態生成的值。

列表解析和生成器表示式

列表解析提供一個簡單的方法對陣列進行小規模操作:

$firstNames = [foreach ($users as $user) yield $user->firstName];  

上述列表解析相等於下面的程式碼:

$firstNames = [];  
foreach ($users as $user) {  
    $firstNames[] = $user->firstName;  
}

也可以這樣過濾陣列:

$underageUsers = [foreach ($users as $user) if ($user->age < 18) yield $user];  

生成器表示式也很類似,但是返回一個迭代器(用於動態生成值)而不是一個陣列。

生成器的返回值

在PHP5.5引入生成器的概念。生成器函式每執行一次就得到一個yield標識的值。在PHP7中,當生成器迭代完成後,可以獲取該生成器函式的返回值。通過Generator::getReturn()得到。

function generator()
{
    yield 1;
    yield 2;
    yield 3;
    return "a";
}

$generatorClass = ("generator")();
foreach ($generatorClass as $val) {
    echo $val ." ";

}
echo $generatorClass->getReturn();

輸出為:1 2 3 a

生成器中引入其他生成器

在生成器中可以引入另一個或幾個生成器,只需要寫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, " ";
}

輸出:1 2 3 4 5 6

finally關鍵字

這個和java中的finally一樣,經典的try … catch … finally 三段式異常處理。

多異常捕獲處理

一個catch語句塊現在可以通過管道字元(|)來實現多個異常的捕獲。 這對於需要同時處理來自不同類的不同異常時很有用。

try {
    // some code
} catch (FirstException | SecondException $e) {
    // handle first and second exceptions
} catch (Exception $e) {
    // ...
} finally{
//
}

foreach 支援list()

對於“陣列的陣列”進行迭代,之前需要使用兩個foreach,現在只需要使用foreach + list了,但是這個陣列的陣列中的每個陣列的個數需要一樣。看文件的例子一看就明白了。

$array = [  
    [1, 2],  
    [3, 4],  
];  
foreach ($array as list($a, $b)) {  
    echo "A: $a; B: $b
";  
} 

短陣列語法 Symmetric array destructuring

短陣列語法([])現在可以用於將陣列的值賦給一些變數(包括在foreach中)。 這種方式使從陣列中提取值變得更為容易。

$data = [
    [`id` => 1, `name` => `Tom`],
    [`id` => 2, `name` => `Fred`],
];
while ([`id` => $id, `name` => $name] = $data) {
    // logic here with $id and $name
}

list()現在支援鍵名

現在list()支援在它內部去指定鍵名。這意味著它可以將任意型別的陣列 都賦值給一些變數(與短陣列語法類似)

$data = [
    [`id` => 1, `name` => `Tom`],
    [`id` => 2, `name` => `Fred`],
];
while (list(`id` => $id, `name` => $name) = $data) {
    // logic here with $id and $name
}

iterable 偽類

現在引入了一個新的被稱為iterable的偽類 (與callable類似)。 這可以被用在引數或者返回值型別中,它代表接受陣列或者實現了Traversable介面的物件。 至於子類,當用作引數時,子類可以收緊父類的iterable型別到array 或一個實現了Traversable的物件。對於返回值,子類可以拓寬父類的 array或物件返回值型別到iterable。

function iterator(iterable $iter)
{
    foreach ($iter as $val) {
        //
    }
}

ext/openssl 支援 AEAD

通過給openssl_encrypt()和openssl_decrypt() 新增額外引數,現在支援了AEAD (模式 GCM and CCM)。
通過 Closure::fromCallable() 將callables轉為閉包
Closure新增了一個靜態方法,用於將callable快速地 轉為一個Closure 物件。

class Test
{
    public function exposeFunction()
    {
        return Closure::fromCallable([$this, `privateFunction`]);
    }
    private function privateFunction($param)
    {
        var_dump($param);
    }
}
$privFunc = (new Test)->exposeFunction();
$privFunc(`some value`);

以上例程會輸出:

string(10) "some value"

匿名類

現在支援通過 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());

Closure::call()

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

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);

為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]);

IntlChar

新增加的 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)

預期

預期是向後兼用並增強之前的 assert() 的方法。 它使得在生產環境中啟用斷言為零成本,並且提供當斷言失敗時丟擲特定異常的能力。 老版本的API出於相容目的將繼續被維護,assert()現在是一個語言結構,它允許第一個引數是一個表示式,而不僅僅是一個待計算的 string或一個待測試的boolean。

ini_set(`assert.exception`, 1);
class CustomError extends AssertionError {}
assert(false, new CustomError(`Some error message`));

以上例程會輸出:
Fatal error: Uncaught CustomError: Some error message

intdiv()

接收兩個引數作為被除數和除數,返回他們相除結果的整數部分。

var_dump(intdiv(7, 2));

輸出int(3)

CSPRNG

新增兩個函式: random_bytes() and random_int().可以加密的生產被保護的整數和字串。總之隨機數變得安全了。
random_bytes — 加密生存被保護的偽隨機字串
random_int —加密生存被保護的偽隨機整數

preg_replace_callback_array()

新增了一個函式preg_replace_callback_array(),使用該函式可以使得在使用preg_replace_callback()函式時程式碼變得更加優雅。在PHP7之前,回撥函式會呼叫每一個正規表示式,回撥函式在部分分支上是被汙染了。

Session options

現在,session_start()函式可以接收一個陣列作為引數,可以覆蓋php.ini中session的配置項。
比如,把cache_limiter設定為私有的,同時在閱讀完session後立即關閉。

session_start([`cache_limiter` => `private`,
               `read_and_close` => true,
]);

$_SERVER[“REQUEST_TIME_FLOAT”]

這個是用來統計服務請求時間的,並用ms(毫秒)來表示

echo "指令碼執行時間 ", round(microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"], 2), "s";  

empty() 支援任意表示式

empty() 現在支援傳入一個任意表示式,而不僅是一個變數

function always_false() {
    return false;
}

if (empty(always_false())) {
    echo `This will be printed.`;
}

if (empty(true)) {
    echo `This will not be printed.`;
}

輸出
This will be printed.

php://input 可以被複用

php://input 開始支援多次開啟和讀取,這給處理POST資料的模組的記憶體佔用帶來了極大的改善。

Upload progress 檔案上傳

Session提供了上傳進度支援,通過$_SESSION[“upload_progress_name”]就可以獲得當前檔案上傳的進度資訊,結合Ajax就能很容易實現上傳進度條了。
詳細的看http://www.laruence.com/2011/10/10/2217.html

大檔案上傳支援

可以上傳超過2G的大檔案。

GMP支援操作符過載

GMP 物件支援操作符過載和轉換為標量,改善了程式碼的可讀性,如:

$a = gmp_init(42);  
$b = gmp_init(17);  

// Pre-5.6 code:  
var_dump(gmp_add($a, $b));  
var_dump(gmp_add($a, 17));  
var_dump(gmp_add(42, $b));  

// New code:  
var_dump($a + $b);  
var_dump($a + 17);  
var_dump(42 + $b);  

JSON 序列化物件

實現了JsonSerializable介面的類的例項在json_encode序列化的之前會呼叫jsonSerialize方法,而不是直接序列化物件的屬性。
參考http://www.laruence.com/2011/10/10/2204.html

HTTP狀態碼在200-399範圍內均被認為訪問成功

支援動態呼叫靜態方法

class Test{    
    public static function testgo()    
    {    
         echo "gogo!";    
    }    
}    
$class = `Test`;    
$action = `testgo`;    
$class::$action();  //輸出 "gogo!"

棄用e修飾符

e修飾符是指示preg_replace函式用來評估替換字串作為PHP程式碼,而不只是僅僅做一個簡單的字串替換。不出所料,這種行為會源源不斷的出現安全問題。這就是為什麼在PHP5.5 中使用這個修飾符將丟擲一個棄用警告。作為替代,你應該使用preg_replace_callback函式。你可以從RFC找到更多關於這個變化相應的資訊。

新增函式 boolval

PHP已經實現了strval、intval和floatval的函式。為了達到一致性將新增boolval函式。它完全可以作為一個布林值計算,也可以作為一個回撥函式。

新增函式hash_pbkdf2

PBKDF2全稱“Password-Based Key Derivation Function 2”,正如它的名字一樣,是一種從密碼派生出加密金鑰的演算法。這就需要加密演算法,也可以用於對密碼雜湊。更廣泛的說明和用法示例

array_column

//從資料庫獲取一列,但返回是陣列。  
$userNames = [];  
foreach ($users as $user) {  
    $userNames[] = $user[`name`];  
}  
//以前獲取陣列某列值,現在如下  
$userNames = array_column($users, `name`);  

一個簡單的密碼雜湊API

$password = "foo";    
// creating the hash    
$hash = password_hash($password, PASSWORD_BCRYPT);    
// verifying a password    
if (password_verify($password, $hash)) {    
    // password correct!    
} else {    
    // password wrong!    
}   

非同步訊號處理 Asynchronous signal handling

A new function called pcntl_async_signals() has been introduced to enable asynchronous signal handling without using ticks (which introduce a lot of overhead).
增加了一個新函式 pcntl_async_signals()來處理非同步訊號,不需要再使用ticks(它會增加佔用資源)

pcntl_async_signals(true); // turn on async signals
pcntl_signal(SIGHUP,  function($sig) {
    echo "SIGHUP
";
});
posix_kill(posix_getpid(), SIGHUP);

以上例程會輸出:

SIGHUP

HTTP/2 伺服器推送支援 ext/curl

Support for server push has been added to the CURL extension (requires version 7.46 and above). This can be leveraged through the curl_multi_setopt() function with the new CURLMOPT_PUSHFUNCTION constant. The constants CURL_PUST_OK and CURL_PUSH_DENY have also been added so that the execution of the server push callback can either be approved or denied.
蹩腳英語:
對於伺服器推送支援新增到curl擴充套件(需要7.46及以上版本)。
可以通過用新的CURLMOPT_PUSHFUNCTION常量 讓curl_multi_setopt()函式使用。
也增加了常量CURL_PUST_OK和CURL_PUSH_DENY,可以批准或拒絕 伺服器推送回撥的執行

php.ini中可使用變數

PHP default_charset 預設字符集 為UTF-8

ext/phar、ext/intl、ext/fileinfo、ext/sqlite3和ext/enchant等擴充套件預設隨PHP繫結釋出。其中Phar可用於打包PHP程式,類似於Java中的jar機制

PHP7.1不相容性

1.當傳遞引數過少時將丟擲錯誤

在過去如果我們呼叫一個使用者定義的函式時,提供的引數不足,那麼將會產生一個警告(warning)。 現在,這個警告被提升為一個錯誤異常(Error exception)。這個變更僅對使用者定義的函式生效, 並不包含內建函式。例如:

function test($param){}
test();

輸出:

Uncaught Error: Too few arguments to function test(), 0 passed in %s on line %d and exactly 1 expected in %s:%d

2.禁止動態呼叫函式

禁止動態呼叫函式如下
assert() – with a string as the first argument
compact()
extract()
func_get_args()
func_get_arg()
func_num_args()
get_defined_vars()
mb_parse_str() – with one arg
parse_str() – with one arg

(function () {
    `func_num_args`();
})();

輸出

Warning: Cannot call func_num_args() dynamically in %s on line %d

3.無效的類,介面,trait名稱命名

以下名稱不能用於 類,介面或trait 名稱命名:
void
iterable

4.Numerical string conversions now respect scientific notation

Integer operations and conversions on numerical strings now respect scientific notation. This also includes the (int) cast operation, and the following functions: intval() (where the base is 10), settype(), decbin(), decoct(), and dechex().

5.mt_rand 演算法修復

mt_rand() will now default to using the fixed version of the Mersenne Twister algorithm. If deterministic output from mt_srand() was relied upon, then the MT_RAND_PHP with the ability to preserve the old (incorrect) implementation via an additional optional second parameter to mt_srand().

6.rand() 別名 mt_rand() 和 srand() 別名 mt_srand()

rand() and srand() have now been made aliases to mt_rand() and mt_srand(), respectively. This means that the output for the following functions have changes: rand(), shuffle(), str_shuffle(), and array_rand().

7.Disallow the ASCII delete control character in identifiers

The ASCII delete control character (0x7F) can no longer be used in identifiers that are not quoted.

8.error_log changes with syslog value

If the error_log ini setting is set to syslog, the PHP error levels are mapped to the syslog error levels. This brings finer differentiation in the error logs in contrary to the previous approach where all the errors are logged with the notice level only.

9.在不完整的物件上不再呼叫析構方法

析構方法在一個不完整的物件(例如在構造方法中丟擲一個異常)上將不再會被呼叫

10.call_user_func()不再支援對傳址的函式的呼叫

call_user_func() 現在在呼叫一個以引用作為引數的函式時將始終失敗。

11.字串不再支援空索引操作符 The empty index operator is not supported for strings anymore

對字串使用一個空索引操作符(例如str[]=x)將會丟擲一個致命錯誤, 而不是靜默地將其轉為一個陣列

12.ini配置項移除

下列ini配置項已經被移除:
session.entropy_file
session.entropy_length
session.hash_function
session.hash_bits_per_character

PHP7.0 不相容性

1、foreach不再改變內部陣列指標

在PHP7之前,當陣列通過 foreach 迭代時,陣列指標會移動。現在開始,不再如此,見下面程式碼。

$array = [0, 1, 2];
foreach ($array as &$val) {
    var_dump(current($array));
}

PHP5輸出:
int(1)
int(2)
bool(false)
PHP7輸出
int(0)
int(0)
int(0)

2、foreach通過引用遍歷時,有更好的迭代特性

當使用引用遍歷陣列時,現在 foreach 在迭代中能更好的跟蹤變化。例如,在迭代中新增一個迭代值到陣列中,參考下面的程式碼:

$array = [0];
foreach ($array as &$val) {
    var_dump($val);
    $array[1] = 1;
}

PHP5輸出:
int(0)
PHP7輸出:
int(0)
int(1)

3、十六進位制字串不再被認為是數字

含十六進位制字串不再被認為是數字

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

PHP5輸出:
bool(true)
bool(true)
int(15)
string(2) “oo”
PHP7輸出
bool(false)
bool(false)
int(0)
Notice: A non well formed numeric value encountered in /tmp/test.php on line 5
string(3) “foo”

4、PHP7中被移除的函式

被移除的函式列表如下:
call_user_func() 和 call_user_func_array()從PHP 4.1.0開始被廢棄。
已廢棄的 mcrypt_generic_end() 函式已被移除,請使用mcrypt_generic_deinit()代替。
已廢棄的 mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() 和 mcrypt_ofb() 函式已被移除。
set_magic_quotes_runtime(), 和它的別名 magic_quotes_runtime()已被移除. 它們在PHP 5.3.0中已經被廢棄,並且 在in PHP 5.4.0也由於魔術引號的廢棄而失去功能。
已廢棄的 set_socket_blocking() 函式已被移除,請使用stream_set_blocking()代替。
dl()在 PHP-FPM 不再可用,在 CLI 和 embed SAPIs 中仍可用。
GD庫中下列函式被移除:imagepsbbox()、imagepsencodefont()、imagepsextendfont()、imagepsfreefont()、imagepsloadfont()、imagepsslantfont()、imagepstext()
在配置檔案php.ini中,always_populate_raw_post_data、asp_tags、xsl.security_prefs被移除了。

5、new 操作符建立的物件不能以引用方式賦值給變數

new 操作符建立的物件不能以引用方式賦值給變數

class C {}
$c =& new C;

PHP5輸出:
Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3
PHP7輸出:
Parse error: syntax error, unexpected ‘new’ (T_NEW) in /tmp/test.php on line 3

6、移除了 ASP 和 script PHP 標籤

使用類似 ASP 的標籤,以及 script 標籤來區分 PHP 程式碼的方式被移除。 受到影響的標籤有:<% %>、<%= %>、

7、從不匹配的上下文發起呼叫

在不匹配的上下文中以靜態方式呼叫非靜態方法, 在 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();

PHP5輸出:
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) {
}
PHP7輸出
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

8、在數值溢位的時候,內部函式將會失敗

將浮點數轉換為整數的時候,如果浮點數值太大,導致無法以整數表達的情況下, 在之前的版本中,內部函式會直接將整數截斷,並不會引發錯誤。 在 PHP 7.0 中,如果發生這種情況,會引發 E_WARNING 錯誤,並且返回 NULL。

9、JSON 擴充套件已經被 JSOND 取代

JSON 擴充套件已經被 JSOND 擴充套件取代。
對於數值的處理,有以下兩點需要注意的:
第一,數值不能以點號(.)結束 (例如,數值 34. 必須寫作 34.0 或 34)。
第二,如果使用科學計數法表示數值,e 前面必須不是點號(.) (例如,3.e3 必須寫作 3.0e3 或 3e3)。

10、INI 檔案中 # 註釋格式被移除

在配置檔案INI檔案中,不再支援以 # 開始的註釋行, 請使用 ;(分號)來表示註釋。 此變更適用於 php.ini 以及用 parse_ini_file() 和 parse_ini_string() 函式來處理的檔案。

11、$HTTP_RAW_POST_DATA 被移除

不再提供 $HTTP_RAW_POST_DATA 變數。 請使用 php://input 作為替代。

12、yield 變更為右聯接運算子

在使用 yield 關鍵字的時候,不再需要括號, 並且它變更為右聯接操作符,其運算子優先順序介於 print 和 => 之間。 這可能導致現有程式碼的行為發生改變。可以通過使用括號來消除歧義。

echo yield -1;
// 在之前版本中會被解釋為:
echo (yield) - 1;
// 現在,它將被解釋為:
echo yield (-1);
yield $foo or die;
// 在之前版本中會被解釋為:
yield ($foo or die);
// 現在,它將被解釋為:
(yield $foo) or die;

PHP 7.1.x 中廢棄的特性

1.ext/mcrypt

mcrypt 擴充套件已經過時了大約10年,並且用起來很複雜。因此它被廢棄並且被 OpenSSL 所取代。 從PHP 7.2起它將被從核心程式碼中移除並且移到PECL中。

2.mb_ereg_replace()和mb_eregi_replace()的Eval選項

對於mb_ereg_replace()和mb_eregi_replace()的 e模式修飾符現在已被廢棄

棄用或廢除

下面是被棄用或廢除的 INI 指令列表. 使用下面任何指令都將導致 錯誤.
define_syslog_variables
register_globals
register_long_arrays
safe_mode
magic_quotes_gpc
magic_quotes_runtime
magic_quotes_sybase
棄用 INI 檔案中以 ‘#’ 開頭的註釋.
棄用函式:
call_user_method() (使用 call_user_func() 替代)
call_user_method_array() (使用 call_user_func_array() 替代)
define_syslog_variables()
dl()
ereg() (使用 preg_match() 替代)
ereg_replace() (使用 preg_replace() 替代)
eregi() (使用 preg_match() 配合 ‘i’ 修正符替代)
eregi_replace() (使用 preg_replace() 配合 ‘i’ 修正符替代)
set_magic_quotes_runtime() 以及它的別名函式 magic_quotes_runtime()
session_register() (使用 SESSION)sessionunregister()(使_SESSION 超全部變數替代)
session_is_registered() (使用 $_SESSION 超全部變數替代)
set_socket_blocking() (使用 stream_set_blocking() 替代)
split() (使用 preg_split() 替代)
spliti() (使用 preg_split() 配合 ‘i’ 修正符替代)
sql_regcase()
mysql_db_query() (使用 mysql_select_db() 和 mysql_query() 替代)
mysql_escape_string() (使用 mysql_real_escape_string() 替代)
廢棄以字串傳遞區域設定名稱. 使用 LC_* 系列常量替代.
mktime() 的 is_dst 引數. 使用新的時區處理函式替代.
棄用的功能:
棄用通過引用分配 new 的返回值.
呼叫時傳遞引用被棄用.
已棄用的多個特性 allow_call_time_pass_reference、define_syslog_variables、highlight.bg、register_globals、register_long_arrays、magic_quotes、safe_mode、zend.ze1_compatibility_mode、session.bug_compat42、session.bug_compat_warn 以及 y2k_compliance。


相關文章