霜天部落 | 专注PHP研发,研究LAMP高性能架构部署与优化

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要快两倍。

Magento Transactions

Drupal 7

在执行 Drupal 事务相比PHP5.6,PHP7证明快两倍。

Drupal Transactions

WordPress 3.6

PHP7 证明自己比 PHP5.6 快两倍,因为在执行 WordPress 事务相比。

Wordpress Transactions

动态语言的比较

Mandelbrot Transactions

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()处理程序需要处理的致命错误。

Exception Hiearchy

示例

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