PHP7教學


PHP7是什麼鬼?

PHP7是PHP程式設計語言的一個主要版本,並號稱是開發Web應用程式的一次革命,可開發和交付移動企業和雲應用。此版本被認為是PHP在2004年發布PHP5後最重要的變化。

新功能

PHP7有加入幾十個功能,最顯著的是下面提到 -
  • 改進的效能 - PHPNG程式碼合併在PHP7中,這是比 PHP5快兩倍;

  • 降低記憶體消耗 - 優化後PHP7使用較少的資源;

  • 標量型別宣告 - 現在,引數和返回值型別可以被強制執行;

  • 一致性的64位元支援 - 64位元架構機器持續支援;

  • 改進異常層次結構 - 異常層次結構得到改善;

  • 許多致命錯誤轉換成異常 - 異常的範圍增大覆蓋為許多致命的錯誤轉化異常;

  • 安全亂數發生器 - 加入新的安全亂數生成器的API;

  • 已過時的API和擴充套件刪除 - 不同的舊的和不支援的應用程式和擴充套件,從最新的版本中刪除;

  • null合併運算子(??)的新空合併運算子被加入;
  • 返回和標量型別宣告支援返回型別和引數型別也被加入;
  • 增加了對匿名匿名類的支援;
  • 零成本宣告支援零成本加入斷言。

PHP7使用新的 Zend Engine 3.0 提高應用程式效能兩倍,比PHP5.6 低了 50% 的記憶體消耗。 它可以服務於更多的並行使用者,無需任何額外的硬體。考慮到當今的工作量 PHP7設計並重構。

PHP7 - 效能

按照Zend開發小組,下圖顯示了流行的基於PHP應用在3.7 HHVM上 PHP7 與 PHP5.6 比較的效能。

Magento 1.9

在執行的Magento事務相比PHP5.6,PHP7要快兩倍。

Drupal 7

在執行 Drupal 事務相比PHP5.6,PHP7證明快兩倍。

Wordpress 3.6

PHP7 證明自己比 PHP5.6 快兩倍,因為在執行 WordPress 事務相比。

動態語言的比較

PHP7 - 環境設定

為了開發和執行PHP Web頁面,需要您在計算機系統上安裝三個重要元件。
  • Web伺服器 ? PHP幾乎能與所有的Web伺服器軟體一起工作,包括微軟的Internet Information Server(IIS),但是最常用的是免費提供的Apache伺服器。 在這裡免費下載Apache ? http://httpd.apache.org/download.cgi

  • 資料庫 ? PHP幾乎能與所有的資料庫軟體工作,其中包括Oracle和Sybase,但最常用的是免費的MySQL資料庫。MySQL在這裡免費下載在 ?http://www.mysql.com/downloads/

  • PHP分析器? 為了處理PHP指令碼的說明必須安裝一個分析器,生成HTML輸出,可以傳送到Web瀏覽器。本教學將指導您如何在您的計算機上安裝PHP解析器。

PHP解析器安裝

在繼續之前,確保你有適當的環境設定在你的機器上,使用PHP開發Web程式是非常重要的。儲存下面的PHP檔案在Apache的htdocs檔案夾中。

phpinfo.php
<?php
phpinfo();
?>
輸入下面的地址在瀏覽器的位址列中,檢視輸出結果。
http://127.0.0.1/phpinfo.php 

如果這顯示了PHP安裝相關資訊的頁面,那麼就意味著PHP和Web伺服器安裝正確。否則,您必須遵循特定程式在計算機上安裝PHP。

本節將指導您安裝並在以下四個平台上組態PHP(本系列教學是基於 Win10上安裝Apache+PHP開發環境) -

Apache組態

如果您使用Apache作為Web伺服器,本節將指導您編輯Apache的組態檔案。

詳細請看這裡? Apache伺服器組態PHP

PHP.INI檔案組態

PHP組態檔案 - php.ini,這會影響 PHP 功能最直接的方式。

Windows IIS組態

如果要在您的Windows計算機上組態IIS,可以參考IIS手冊。

PHP7 - 標量型別宣告

在PHP7有一個新的功能,標量型別宣告已被引入。標量型別宣告有兩種選擇:
  • 強制 - 強制性是預設模式,不需要指定。

  • 嚴格 - 嚴格模式有明確的暗示。

以下幾種型別的函式引數可以通過上述方式強制執行:
  • int

  • float

  • bool

  • string

  • interfaces

  • array

  • callable

範例 - 強制模式

<?php
// Coercive mode
function sum(int ...$ints)
{
   return array_sum($ints);
}

print(sum(2, '3', 4.1));
?>
瀏覽器將產生以下輸出 -
9

範例 - 嚴格模式

<?php
// Strict mode
declare(strict_types=1);

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

print(sum(2, '3', 4.1));
?>
瀏覽器將產生以下輸出 -
Fatal error: Uncaught TypeError: Argument 2 passed to sum() must be of the type integer, string given, ...

PHP7 - 返回型別宣告

在PHP7中有一個新的功能,已引入返回型別宣告。返回型別宣告指定一個函式的返回值型別。以下型別返回型別是可以宣告的:

  • int

  • float

  • bool

  • string

  • interfaces

  • array

  • callable

範例 - 有效的返回型別

<?php
declare(strict_types=1);

function returnIntValue(int $value): int
{
   return $value;
}

print(returnIntValue(5));
?>
瀏覽器將產生以下輸出-
5

範例 - 無效的返回型別

<?php
declare(strict_types=1);

function returnIntValue(int $value): int
{
   return $value + 1.0;
}

print(returnIntValue(5));
?>
這將產生以下瀏覽器輸出 -
Fatal error: Uncaught TypeError: Return value of returnIntValue() must be of the type integer, float returned...

PHP7 - Null合併運算子

PHP7一個新的功能,空合併運算子(??)已經推出。它是用來與isset()函式函式一起替換三元操作。如果存在且不是 NULL 空合併運算子返回它的第一個運算元;否則返回第二個運算元。

範例

<?php
// fetch the value of $_GET['user'] and returns 'not passed'
// if username is not passed
$username = $_GET['username'] ?? 'not passed';

print($username);
print("<br/>");


// Equivalent code using ternary operator
$username = isset($_GET['username']) ? $_GET['username'] : 'not passed';

print($username);
print("<br/>");
// Chaining ?? operation
$username = $_GET['username'] ?? $_POST['username'] ?? 'not passed';

print($username);
?>
這將在瀏覽器產生以下輸出 -
not passed
not passed
not passed

PHP7飛船操作符

在PHP7中有一個新的功能-飛船操作符相繼引入。它是用於比較兩個表示式。當第一個表示式較第二個表示式分別小於,等於或大於時它分別返回-1,0或1。

範例

<?php
//integer comparison
print( 1 <=> 1);print("<br/>");
print( 1 <=> 2);print("<br/>");
print( 2 <=> 1);print("<br/>");
print("<br/>");
//float comparison
print( 1.5 <=> 1.5);print("<br/>");
print( 1.5 <=> 2.5);print("<br/>");
print( 2.5 <=> 1.5);print("<br/>");
print("<br/>");
//string comparison
print( "a" <=> "a");print("<br/>");
print( "a" <=> "b");print("<br/>");
print( "b" <=> "a");print("<br/>");
?>

這將在瀏覽器產生以下輸出 -

0
-1
1

0
-1
1

0
-1
1

PHP7 - 常數陣列

陣列常數現在可以使用 define() 函式定義。在PHP5.6中,它們只能使用const關鍵字定義。

範例

<?php
//define a array using define function
define('animals', [
   'dog',
   'cat',
   'bird'
]);

print(animals[1]);
?>

這將在瀏覽器產生以下輸出 -

cat

PHP7 - 匿名類

匿名類現在可以使用 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) {
      print($msg);
   }
});

$app->getLogger()->log("My first Log Message");
?>

這將在瀏覽器產生以下輸出 -

My first Log Message

PHP7 - Closure::call()

Closure::call() 方法加入到臨時繫結(bindTo)的物件範圍,以簡便方式封閉和呼叫它 它相比系結到PHP5.6效能更快。

範例 - PHP7之前版本

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

// Define a closure Pre PHP 7 code
$getValue = function() {
   return $this->x;
};

// Bind a clousure
$value = $getValue->bindTo(new A, 'A'); 

print($value());
?>

這將在瀏覽器產生以下輸出 -

1

範例-PHP7+

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

// PHP 7+ code, Define
$value = function() {
   return $this->x;
};

print($value->call(new A));
?>

這將在瀏覽器產生以下輸出 -

1

PHP7- 過濾unserialize()

PHP7引入了過濾 unserialize()函式以在反序列化不受信任的資料物件時提供更好的安全性。它可以防止可能的程式碼注入,使開發人員能夠使用序列化白名單類。

範例

<?php
class MyClass1 { 
   public $obj1prop;   
}
class MyClass2 {
   public $obj2prop;
}


$obj1 = new MyClass1();
$obj1->obj1prop = 1;
$obj2 = new MyClass2();
$obj2->obj2prop = 2;

$serializedObj1 = serialize($obj1);
$serializedObj2 = serialize($obj2);

// default behaviour that accepts all classes
// second argument can be ommited.
// if allowed_classes is passed as false, unserialize converts all objects into __PHP_Incomplete_Class object
$data = unserialize($serializedObj1 , ["allowed_classes" => true]);

// converts all objects into __PHP_Incomplete_Class object except those of MyClass1 and MyClass2
$data2 = unserialize($serializedObj2 , ["allowed_classes" => ["MyClass1", "MyClass2"]]);

print($data->obj1prop);
print("<br/>");
print($data2->obj2prop);
?>

這將在瀏覽器產生以下輸出 -

1
2

PHP7 - 國際字元

在PHP7,新的 IntlChar 類新增其目的是公開更多的ICU功能。 這個類定義了許多可用於操縱Unicode字元的靜態方法和常數。你需要在使用這個類之前安裝 Intl 擴充套件。

範例

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

這將在瀏覽器產生以下輸出 -

10ffff
COMMERCIAL AT
true

PHP7 - CSPRNG

在PHP7,以下兩個新的函式引入以產生一個跨平台的方式加密安全整數和字串。
  • random_bytes() - 生成加密安全偽隨機位元組。

  • random_int() - 生成加密安全偽隨機整數。

random_bytes()

random_bytes()適合於使用來生成密碼,密碼學隨機的任意長度的字串,如:生成 salt,金鑰或初始向量。

語法

string random_bytes ( int $length )

引數

  • length - 返回隨機串的位元組長度

返回值

  • 返回包含加密安全隨機位元組的請求數量的字串。

錯誤/異常

  • 如果無法找到隨機性的適當源,將引發異常
  • 如果給定引數無效,TypeError將被丟擲
  • 如果給出位元組長度無效,錯誤將被丟擲

範例

<?php
$bytes = random_bytes(5);
print(bin2hex($bytes));
?>

這將在瀏覽器產生以下輸出 -

54cc305593

random_int()

random_int()產生適合於用於結果是非常重要的加密隨機整數。

語法

int random_int ( int $min , int $max )

引數

  • min - 返回最小值,它必須是PHP_INT_MIN或更大的值

  • max - 返回最大值,它必須是小於或等於PHP_INT_MAX

返回值

  • 返回最小值(min)到最大(max)的範圍內,包括加密安全隨機整數。

錯誤/異常

  • 如果無法找到隨機性一個適當的源,將引發異常
  • 如果給定引數無效,TypeError 將被丟擲
  • 如果 max 小於 min 時,錯誤將被丟擲

範例

<?php
print(random_int(100, 999));
print("
");
print(random_int(-1000, 0));
?>

這將在瀏覽器產生以下輸出 -

614
-882

PHP7 - 期望

期望是向後相容的增強到舊 assert() 函式。期望允許在生產程式碼零成本的斷言,並提供在斷言失敗時丟擲自定義異常的能力。assert() 不是一種語言構建體,其中第一個引數是一個表示式的比較字串或布林用於測試。

組態指令assert()

指令 預設值 
可能的值
zend.assertions 1
  • 1 - 生成並執行程式碼(開發模式)

  • 0 - 生成程式碼,但它在執行時

  • -1 - 不生成程式碼(生產模式)

assert.exception 0
  • 1 - 當斷言失敗時丟擲,要麼丟擲的異常,或者通過丟擲一個新的 AssertionError 物件提供的物件,如果沒有提供異常

  • 0 - 使用或與上述生成的Throwable,但只能根據該物件的警告,而不是(與PHP 5相容的行為)把它丟擲

引數

  • assertion - 斷言。在PHP 5中,這必須是要計算一個字串或要測試一個布林值。 在PHP中7,這也可能是一個返回值的表示式,將執行和使用的結果,以指示斷言是成功還是失敗。

  • description - 一個可選的描述,如果斷言失敗,將包括失敗訊息。

  • exception-在PHP7,第二個引數可以是一個 Throwable 物件,而不是一個描述字串,在這種情況下,這是如果斷言失敗和assert.exception組態指令啟用將丟擲的物件。

返回值

如果斷言為假為FALSE,否則為TRUE。

範例

<?php
ini_set('assert.exception', 1);

class CustomError extends AssertionError {}

assert(false, new CustomError('Custom Error Message!'));
?>

這將在瀏覽器產生以下輸出 -

Fatal error: Uncaught CustomError: Custom Error Message! in...

PHP7 - use語句

從PHP7起,單次使用 use 語句可以用來從同一個名稱空間匯入類,函式和常數(而不用多次使用 use 語句)。

範例

<?php
// Before PHP 7
use com\yiibai\ClassA;
use com\yiibai\ClassB;
use com\yiibai\ClassC as C;

use function com\yiibai\fn_a;
use function com\yiibai\fn_b;
use function com\yiibai\fn_c;

use const com\yiibai\ConstA;
use const com\yiibai\ConstB;
use const com\yiibai\ConstC;

// PHP 7+ code
use com\yiibai\{ClassA, ClassB, ClassC as C};
use function com\yiibai\{fn_a, fn_b, fn_c};
use const com\yiibai\{ConstA, ConstB, ConstC};

?>

PHP7 - 錯誤處理

從PHP7,錯誤處理和報告已經改變。PHP5中使用了傳統的錯誤報告機制的錯誤,現在大多數的錯誤將通過丟擲異常錯誤處理。類似於異常,這些錯誤異常會冒泡,直到它們到達第一個匹配的catch塊。如果沒有匹配的塊,那麼會使用 set_exception_handler() 安裝一個預設的例外處理並被呼叫,並在情況下,如果沒有預設的例外處理程式,那麼該異常將被轉換為一個致命的錯誤,並會像傳統錯誤那樣處理。

由於 Error 層次結構不是從異常(Exception),程式碼擴充套件使用catch (Exception $e) { ... } 塊來處理未捕獲的異常,PHP5中將不會處理這樣的錯誤。  catch (Error $e) { ... } 塊或 set_exception_handler()處理程式需要處理的致命錯誤。

範例

<?php
class MathOperations 
{
   protected $n = 10;

   // Try to get the Division by Zero error object and display as Exception
   public function doOperation(): string
   {
      try {
         $value = $this->n % 0;
         return $value;
      } catch (DivisionByZeroError $e) {
         return $e->getMessage();
      }
   }
}

$mathOperationsObj = new MathOperations();
print($mathOperationsObj->doOperation());
?>
瀏覽器中將產生以下輸出-
Modulo by zero

PHP7 - 整數除法

PHP7引入了intdiv()的新函式,它執行運算元的整數除法並返回結果為 int 型別。

範例

<?php
$value = intdiv(10,3);
var_dump($value);
print("
");
print($value);
?>

這將在瀏覽器產生以下輸出 -

int(3) 
3

PHP7 - Session選項

從PHP7+,session_start()函式接受陣列引數覆蓋在php.ini中設定的對談組態指令。這些選項支援 session.lazy,在預設情況下如果PHP對談資料改變,那麼會覆蓋任何對談資料資訊。

新增另一種選擇是:read_and_close,這表明對談資料應被讀取,然後該對談應當立即被關閉不變。例如,session.cache_limiter 設定為私有,並設定標誌使用下面的程式碼片段之後立即關閉對談。
<?php
session_start([
   'cache_limiter' => 'private',
   'read_and_close' => true,
]);
?>

PHP7 - 棄用的功能

以下功能已被取消,可能會在PHP的未來版本中刪除。

PHP4風格的建構函式

PHP4式建構函式,它與類的名稱相同,因為它們是在所定義類的方法,現在已過時,並且將在未來被移除。如果PHP4的構造僅僅是一個類中定義建構函式,PHP7將發出E_DEPRECATED。類實現建構函式 __construct()方法不受影響。

範例

<?php
class A {
   function A() {
      print('Style Constructor');
   }
}
?>

這將在瀏覽器產生以下輸出 -

Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; A has a deprecated constructor in...

靜態呼叫非靜態方法

非靜態方法靜態呼叫已被棄用,並且可能在將來被移除。

範例

<?php
class A {
   function b() {
      print('Non-static call');
   }
}
A::b();
?>

這將在瀏覽器產生以下輸出 -

Deprecated: Non-static method A::b() should not be called statically in...
Non-static call

password_hash() salt 選項

password_hash()函式的salt選項已被棄用,使開發人員不會產生他們自己的(通常是不安全的)salt。函式本身生成一個加密的安全salt,在開發者沒有提供salt值時 - 因此,客製化 salt 生成不再需要了。

capture_session_meta SSL上下文選項

capture_session_meta SSL上下文選項已被棄用。 SSL後設資料現在通過stream_get_meta_data()函式獲取。

PHP7已刪除的擴充套件

以下擴充套件名從PHP7起刪除
  • ereg

  • mssql

  • mysql

  • sybase_ct

PHP7已刪除的SAPI

以下SAPI從PHP7起刪除
  • aolserver

  • apache

  • apache_hooks

  • apache2filter

  • caudium

  • continuity

  • isapi

  • milter

  • nsapi