1. 程式人生 > 實用技巧 >php7的新特性

php7的新特性

都知道吃別人嚼過的東西不香,那也得吃,總比餓著強。誰讓自己的牙沒長全(英語,計算機基礎)。七拼八湊組合一下,加上自己的理解。重點還是要多看多學,哪怕一篇文章只吸取了那麼一丁點的知識,也要自己加工,形成自己的知識體系。不要當吃瓜群眾,囫圇吞棗的看一下,沒過幾天就忘了,文章是沒少看,最後一無所獲,回頭來還要花同樣的時間再次學習。

null 合併運算子

由於日常使用中存在大量同時使用三元表示式和 isset()的情況, 我們添加了null合併運算子(_??_)這個語法糖。如果變數存在且值不為NULL, 它就會返回自身的值,否則返回它的第二個運算元。

$name = isset($_GET['name']) ? $_GET['name'] : 'nobody';
// 等價於 $_GET['name'] 存在且值不為NULL 就返回自身的值,否則為設定的值
$name = $_GET['name'] ?? 'nobody';

$a = null;
$name = $a ?? 0; 
echo $name ; // 輸出 0

太空操作符

太空船操作符用於比較兩個表示式。當小於、等於或大於b時它分別返回-1、0或1

//整數  
echo 1 <=> 1; //0  
echo 1 <=> 2; //-1  
echo 2 <=> 1; //1  
  
//浮點數  
echo 1.5 <=> 1.5; //0  
echo 1.5 <=> 2.5; //-1  
echo 2.5 <=> 1.5; //1  
  
//字串  
echo "a" <=> "a"; //0  
echo "a" <=> "b"; //-1  
echo "b" <=> "a"; //1

通過define()定義常量陣列

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

define("nba", [
    '湖人',
    '雷霆',
    '熱火',
    '火箭'
]);

print_r(nba); 

// 輸出 與陣列的操作方式一樣了
// Array
// (
//     [0] => 湖人
//     [1] => 雷霆
//     [2] => 熱火
//     [3] => 火箭
// )

標量型別宣告

標量型別宣告 有兩種模式: 強制 (預設) 和 嚴格模式。 現在可以使用下列型別引數(無論用強制模式還是嚴格模式): 字串(string), 整數 (_int_), 浮點數 (float), 以及布林值 (_bool_)。它們擴充了php5中引入的其他型別:類名,介面,陣列和 回撥型別。

function testInt(int ...$ints) {
    return array_sum($ints);
}

function testString(string $a, string $b) {
    echo $a . $b . "\n";
}

function testArr(array $arr) {
    print_r($arr);
}

匿名類

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

interface Logger {
    public function log(string $msg);
}

class Application {
    
    private $logger;

    /**
     * 返回 logger
     *
     * @return Logger
     */
    public function getLogger(): Logger {
        $this->logger->log("abc");
        return $this->logger;
    }

    /**
     * 設定 logger 變數
     *
     * @param Logger $logger
     * @return void
     */
    public function setLogger(Logger $logger) {
        $this->logger = $logger;
    }
}

$app = new Application;
$app->setLogger(new class implements Logger {

    /**
     * 匿名類實現 logger 的 log
     *
     * @param string $msg
     * @return void
     */
    public function log(string $msg) {
        echo sprintf("這是匿名函式實現的 log , msg=%s\n", $msg);
    }
});

var_dump($app->getLogger());

// 輸出結果
這是匿名函式實現的 log , msg=abc
object(class@anonymous)#2 (0) {
}

Unicode codepoint 轉譯語法

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

echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";

輸出結果

ª
ª (same as before but with optional leading 0's)
香

Closure::call()

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

class A {private $x = 100;}

// PHP 7 之前版本的程式碼
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // 中間層閉包
echo $getX();

// PHP 7+ 及更高版本的程式碼
// 將匿名函式繫結到 A 類中,並且以匿名函式的身份呼叫
$getX = function() {return $this->x;};
echo $getX->call(new A);

為unserialize()提供過濾

// 將所有的物件都轉換為 __PHP_Incomplete_Class 物件
$data = unserialize($foo, ["allowed_classes" => false]);

// 將除 MyClass 和 MyClass2 之外的所有物件都轉換為 __PHP_Incomplete_Class 物件
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]);

// 預設情況下所有的類都是可接受的,等同於省略第二個引數
$data = unserialize($foo, ["allowed_classes" => true]);

IntlChar

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

以上例程會輸出:

10ffff
COMMERCIAL AT
bool(true)

整數除法函式intdiv()

新加的函式 intdiv() 用來進行 整數的除法運算。

var_dump(intdiv(10, 3));

以上輸出

int(3)

Group use declarations

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

// PHP 7 之前的程式碼
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;

use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;

use const some\namespace\constA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;

// PHP 7+ 及更高版本的程式碼
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};

擴充套件declare

每執行一條語句,就會呼叫一次register_tick_function()註冊的函式,可以來控制程式的執行時間等功能

declare(ticks=1);

// 開始時間
$glnum = 0;

// 檢查是否已經超時
function check_timeout(){
    global $glnum;
    $glnum ++;
    echo sprintf("呼叫了%s次" . "\n", $glnum);
}
// Zend引擎每執行一次低階語句就執行一下check_timeout
register_tick_function('check_timeout');

// 假設業務處理
function yunwu() {
    $a = 1;
    $b = 2;
    $c = 3;
}
yunwu();

// 輸出結果
呼叫了1次
呼叫了2次
呼叫了3次
呼叫了4次
呼叫了5次
呼叫了6次

生成器可以返回表示式

此特性基於 PHP 5.5 版本中引入的生成器特性構建的。 它允許在生成器函式中通過使用return語法來返回一個表示式 (但是不允許返回引用值), 可以通過呼叫Generator::getReturn()方法來獲取生成器的返回值, 但是這個方法只能在生成器完成產生工作以後呼叫一次。

function createRange($number){
    for($i=0;$i<$number;$i++){
        yield time();
    }
}

$result = createRange(10); // 這裡呼叫上面我們建立的函式
foreach ($result as $val) {
    sleep(1);
    echo $val, PHP_EOL;
}

應用場景:讀取大的檔案節省記憶體

廣州設計公司https://www.houdianzi.com 我的007辦公資源網站https://www.wode007.com

預期

預期是向後兼用並增強之前的 assert() 的方法。 它使得在生產環境中啟用斷言為零成本,並且提供當斷言失敗時丟擲特定異常的能力。

老版本的API出於相容目的將繼續被維護,assert()現在是一個語言結構,它允許第一個引數是一個表示式,而不僅僅是一個待計算的 string或一個待測試的boolean。

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