PHP新版本變化

世界變化真快,忽然聽聞 PHP 都到 7.3 版本了,7.2 還沒仔細瞭解過呢。看到我司面試時會問到php新版本有什麼特性,美名其曰考察其學習新技術的能力,我有點汗顏,本身都沒有主動去了解過,實在不該該。所以,在這裏立下一貼,用於記錄新版本的PHP的變化,以及對實際工做的影響。php

PHP 7.0

PHP7.0 號稱是性能提高上革命性的一個版本。面對 Facebook 家的 HHVM 引擎帶來的壓力,開發團隊重寫了底層的 Zend Engine,名爲 Zend Engine 2。面試

雖然是大版本的更新(直接從PHP5.6跳到了7,中間省略了不存在的6),可是幾乎不會遇到兼容性的問題,不會像 Python 那樣陷入 2.7 或 3.7 的選擇困境。咱們本身在評估測試了實際項目運行狀況以後,直接升到了 7.1。數組

下面講一講主要的變化:安全

新增

標量類型聲明

類型聲明也叫 type hints,即聲明參數的類型。如今能夠聲明參數爲標量類型了,包括:string,int,float,bool。擴充了原來的範圍,原來只支持:類名,接口名,''array'' 和 ''callable'' 這五種類型。session

<?php

function sum(int $a, int $b)
{
    return $a + $b;
}

var_dump(sum(1, 2));

// output: int(3)

返回值類型聲明

函數能夠添加返回值類型聲明瞭,聲明返回值的類型。能夠聲明的類型範圍與參數聲明類型相同。閉包

function sum(int $a, int $b): int
{
    return $a . $b;
}

var_dump(sum(1, 2));

// output: int(12)

function sum(int $a, int $b): string
{
    return $a . $b;
}

var_dump(sum(1, 2));

// output: string(2) "12"

?? 操做符

'''??'''操做符簡化了'''isset()'''函數的使用,若是第一個操做數存在且不爲NULL,則返回之,不然返回第二個操做數。app

<?php
// 這種場景,判斷是否存在,若是不存在則賦值默認一個值
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// 使用 ?? 得到相同效果,代碼卻簡潔不少
$username = $_GET['user'] ?? 'nobody';

// ?? 能夠鏈式使用,第一個不存在,則判斷第二個,第二個不存在再使用默認值
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';

<=> 操做符

'''<=>''' 操做符用於比較兩個表達式。能夠把這個操做符拆開來理解,'''<=>''' 一次就能判斷出 小於<,等於=,大於> 這三種狀況。dom

<?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
?>

使用 define() 定義常量數組

如今可使用 define() 來定義常量數組了,而以前只能用 const 定義。socket

<?php
define('ANIMALS', [
    'dog',
    'cat',
    'bird',
]);

echo ANIMALS[1];

匿名類

如今支持匿名類了。函數

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

// output:
// class class@anonymous#2 (0) {
// }

匿名類至少方便了如下場景:(1)測試更方便,爲接口建立實時實現,而不用專門去創建一個只用一次的類。

Unicode 轉義語法

語法以下例所示,能夠直接經過16進制的代碼來輸出 Unicode 字符了。

echo "\u{5201}";
echo "\u{2200}";
// output: 刁
// output: ∀

Closure::call()

Closure::call() 是一種更加簡潔的方式,來綁定對象到閉包並調用它。

<?php
class A
{
    private $x = 1;
}

$getX = function () {
    return $this->x;
};

// pre PHP7
$getXCB = $getX->bindTo(new A, 'A');
echo $getXCB();

// PHP7
echo $getX->call(new A);

過濾的 unserialize()

增長了反序列化對象時的安全性。開發者能夠經過第二個參數來設置一個容許反序列化的類的白名單。

<?php
// 轉換全部數據爲 __PHP_Incomplete_Class 對象
$data = unserialize($foo, ["allowed_classes" => false]);
// 轉換全部數據爲 __PHP_Incomplete_Class 對象,除了 MyClass 和 MyClass2
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
// 默認行爲,至關於忽略了第二個參數,容許全部的類
$data = unserialize($foo, ["allowed_classes" => true]);

IntlChar

增長了新的類 '''IntlChar''',它增長了國際化相關的功能,該類定義了大量的靜態方法和靜態常量,用於控制 Unicode 字符。

使用該類,前提是安裝了 Intl 擴展。

Expectations

Expectations 是 assert() 的向後兼容的加強。在php.ini中增長了 assert.expectation 指令以控制 assert() 的行爲。

use 聲明分組

能夠將多個use聲明合併爲一個use

<?php
// pre PHP7
use some\namespace1\ClassA;
use some\namespace1\ClassB;
use some\namespace1\ClassC as C;

// PHP7+
use some\namespace1\{ClassA, ClassB, ClassC as C};

生成器能夠返回表達式

如今生成器能夠用return來返回最後一次的表達式,這個值能夠用新的 Generator::getReturn() 方法獲取,可是這個方法只能在 yield 值結束以後,使用一次。

<?php
$gen = (function () {
    yield 1;
    yield 2;

    return 3;
})();

foreach ($gen as $val) {
    echo $val;
}

echo $gen->getReturn();

// output: 123

這是一個很方便的功能,客戶端使用生成器時能夠用它來判斷 yield 值是否完成。

生成器委託

如今,只需在最外層生成器中使用 yield from, 就能夠把一個生成器自動委託給其餘的生成器、, Traversable 對象或者 array。

<?php
function gen1()
{
    yield 1;
    yield 2;
    yield from gen2();
    yield from [5, 6];
}

function gen2()
{
    yield 3;
    yield 4;
}

foreach (gen1() as $val) {
    echo $val, PHP_EOL;
}

/* output:
1
2
3
4
5
6
*/

不瞭解生成器?能夠參考:《Modern_PHP》#GeneratorsGenerators_(PHP)

使用 intdiv() 進行整數除法

var_dump(intdiv(10, 3));
// output: int(3)

session 選項

如今 session_start() 能夠接受一個 options 數組,以重寫 php.ini 中的 session 設置。

// 設置 session.cache_limiter 爲私有,而且讀取完就關閉session
session_start([
    'cache_limiter' => 'private',
    'read_and_close' => true,
]);

CSPRNG 函數

新增兩個生成加密整數和字符串的函數:random_bytes()random_int()

PHP 7.1

新增

Nullable 類型

如今能夠在參數類型聲明和返回值類型聲明的類型前面加一個問號(?),來表示參數能夠是NULL或者能夠返回NULL值。

<?php
function fun1(?int $i) :?string
{
    if ($i ### null) {
        return null;
    } else {
        return $i;
    }
}

var_dump(fun1(null));
var_dump(fun1(1));

// output: NULL
// output: string(1) "1"
// PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments to function fun1(), 0 passed

Void 函數

新增函數的 void 返回值。void函數要麼沒有return語句,要麼空return語句,返回NULL是錯誤的。

Symmetric array destructuring

短數組語法([])能夠做爲list()語法的另外一種形式,用來給數組賦值。

$data = [
    [1, 'Tom'],
    [2, 'Fred']
];

// list() style
list($id1, $name1) = $data[0];

// [] style
[$id2, $name2] = $data[1];

// list() style
foreach ($data as list($id, $name)) {
    # code...
}

// [] style
foreach ($data as [$id, $name]) {
    # code...
}

類常量可見性

增長了對類常量可見性的支持。

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

iterable 僞類

增長了新的僞類:iterable,能夠用於參數,或返回值類型,表示接受數組或實現了 Traversable 接口的對象。

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

多重 catch 捕獲

能夠在一個catch中捕獲多種異常對象了。

function triError(bool $i)
{
    try {
        if ($i) {
            throw new Exception('exception!');
        } else {
            throw new ErrorException('error exception!');
        }
    } catch(Exception | ErrorException $e) {
        echo $e->getMessage(), PHP_EOL;
    }
}

triError(true);
triError(false);

// output: exception!
// output: error exception!

list() 能夠指定鍵名

如今能夠在 list() 或短數組語法([])中指定鍵名,這樣就能夠支持非數字索引的數組賦值了。

$data = [
    ["id" => 1, "name" => "Tom"],
    ["id" => 2, "name" => "Fred"],
];

list("id" => $id1, "name" => $name1) = $data[0];

var_dump($id1);
var_dump($name1);

// int(1)
// string(3) "Tom"

["id" => $id2, "name" => $name2] = $data[1];

var_dump($id2);
var_dump($name2);

// int(2)
// string(4) "Fred"

支持負的字符串下標

字符串函數以及字符串下標如今能夠爲負數。負數表示從字符串末尾開始執行相關操做。

var_dump("abcde"[-1]);
var_dump(strpos("abcdeb", "b", -1));
var_dump(strpos("abcdeb", "b", 1));

// string(1) "e"
// int(5)
// int(1)

Closure::fromCallable()

增長了一個靜態方法 fromCallable(),用於方便地轉換 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"

PHP 7.2

新增

object 類型

參數類型和返回值類型聲明如今支持 object 類型了,該類型表示接受任何對象。

function test(object $obj): object
{
    return new stdClass();
}

test(new stdClass());

經過名字加載擴展

加載擴展不須要文件擴展名了(.so或.dll),直接用名字便可,在php.ini或者dl()函數都有效。

抽象方法重寫

當一個抽象類繼承另外一個抽象類時,它能夠重寫父類(抽象類)的方法。

abstract class A
{
    abstract public function test(string $s);
}

abstract class B extends A
{
    abstract public function test($s): int;
}

Sodium 成爲核心擴展

現代 Sodium 加密庫已經成爲PHP核心擴展。

使用 Argon2 進行密碼哈希

Argon2 已經被添加到 password hash API中,經過如下常量使用:
PASSWORD_ARGON2I
PASSWORD_ARGON2_DEFAULT_MEMORY_COST
PASSWORD_ARGON2_DEFAULT_TIME_COST
PASSWORD_ARGON2_DEFAULT_THREADS

擴展PDO字符串類型

新增這些常量,擴展了PDO字符串的使用
PDO::PARAM_STR_NATL
PDO::PARAM_STR_CHAR
*PDO::ATTR_DEFAULT_STR_PARAM

$db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL);

Socket擴展新增地址信息獲取

新增下列方法,能夠在鏈接時、綁定時或解釋時查看地址信息:
socket_addrinfo_lookup()
socket_addrinfo_connect()
socket_addrinfo_bind()
socket_addrinfo_explain()

參數類型擴展了

重寫方法的參數類型如今被忽略了,so?

interface A
{
    public function Test(array $input);
}

class B implements A
{
    public function Test($input){} // type omitted for $input
}

分組的命名空間末尾容許逗號

use Foo\Bar\{
    Foo,
    Bar,
    Baz,
};

ZIP擴展加強

支持讀寫加密的壓縮文件了(須要 libzip 1.2.0)

如今 ZipArchive 實現了 Countable 接口。

zip:// 流接受一個 password 上下文選項

PHP 7.3

References

  • https://wiki.php.net/rfc/anonymous_classes
  • https://en.wikipedia.org/wiki/Code_point
  • http://www.avelx.co.uk/unicode-codepoint-escape-syntax/

PS:我的博客連接 PHP新版本變化***

相關文章
相關標籤/搜索