技术开发 频道

初步了解 PHP V6 中的新特性

  【IT168 技术文档】 

  简介

  “PHP 的特性” 简单介绍了 PHP V6 中的新特性。在本文中,了解这些让 PHP V6 更加容易使用、更加安全和更加适合国际化的新特性。本文探索改进的 Unicode 支持,删除了几个函数、改进的扩展、引擎添加内容、改进的面向对象函数和 PHP V6 中的一些扩展。

  增强对 Unicode 的支持

  PHP V6 中的主要特性是增强对 Unicode 的支持。目前,PHP 实际上是一个二进制处理器。PHP V5 没有提供原生的 Unicode 支持;它假定所有字符的长度都为 1 字节,这在处理非拉丁字符时会出现问题。您可以转换到 Unicode,但需要使用 mbstring 扩展,而默认的 PHP V5 或外部工具(比如 iconv)都不支持该扩展。

  PHP V5 有时不能正确显示文本,这取决于字符编码。Unicode 是由 Unicode Consortium 开发的行业标准,它能表示所有语言、程序和平台上的每一个字符。各个行业和标准都广泛支持 Unicode,这使得实现国际化多语言应用程序成为可能。Unicode 可以使用多种字符编码表示,最常见的是 UTF-8、UTF-16 和 UTF-32。

  PHP V6 原生地支持 Unicode (UTF-8),因此它的引擎、扩展和 API 都支持 Unicode。尽管已经添加将所有二进制字符串作为不同类型处理的支持,PHP V6 仍然能够将字符串作为 Unicode 处理。在 PHP V6 中,字符串的字面量为 Unicode,允许使用 Unicode 标识符,并且它的函数能够理解 Unicode 文本。PHP V6 能够在需要时支持 Unicode 字符串和其他编码之间的转换,并支持对 UTF-8 文件进行读写。下面给出一个从 UTF-8 文件读取内容的例子:  

$input = fopen('inputfile.txt', 'rt');

  $str
= fread($input, 100); // returns 100 Unicode characters

  向 UTF-8 文本文件写一个 Unicode 字符串 $uni:  

$output = fopen('outputfile.txt', 'wt');

fwrite($fp, $uni);
// writes out data in UTF-8 encoding

  Unicode 模式

  在 PHP V5 中,可以根据需求将 Unicode 模式设置为打开或关闭。这表明非 Unicode 和 Unicode 变体类、方法和函数名必须存储在符号表中,这导致更多的开销。PHP V6 在 php.ini 中提供一个服务器通用的配置设置,以启用或禁用 Unicode 模式。 Opcode 缓存用于缓存已编译的 PHP 代码。

  服务器通用的配置使引擎的某个部分的实现更加容易,引起的 opcode 缓存问题更少,并且提高运行速度,因为不需要在运行时转换符号名。

  PHP V6 保留了禁用 Unicode 模式的选项,因为一些字符串函数的 Unicode 实现变慢了 300%,这使整个应用程序的速度变慢 25%。PHP V6 在 php.ini 中提供一个运行时配置选项,用于启用或禁用 Unicode 语义。默认设置为 on。

  unicode.semantics = on

  将 unicode.semantics 设置为 off 并不意味着不使用 Unicode。当设置为 off 时,您仍然可用访问 Unicode 特性。当 Unicode 语义设置为 off,字符串的字面量是 8 位的字符串;1 个字符等于 1 个字节。 

   unicode.semantics = off

  $str
= "Hello, world!";// ASCII encoding

  echo strlen($str);
//result is 13

  如果设置为 unicode.semantics=on,那么字符串字面量使用 Unicode 类型。当 Unicode 语义设置为 on 时,一个字符可能 > 1 个字节。  

   unicode.semantics = on

  $str
= "Hello, world!";// Unicode string

  echo strlen($str);
// result is 13

  PHP V6 中的 unicode.runtime_encoding 配置选项指定在运行时执行 Unicode 和二进制字符串之间的转换时使用哪种编码。例如,将运行时编码设置为 iso-8859-1。

 

  unicode.runtime_encoding = iso-8859-1

  当与尚未支持 Unicode 的函数连接时,仍然需要使用运行时编码。PHP 脚本可以采用各种编码方式。PHP V6 提供 unicode.script_encoding 配置选项来指定脚本的编码。不管脚本的编码是什么,生成的字符串字面量都为 Unicode 类型。  

   unicode.script_encoding = iso-8859-1

  $uni
= ""; // Unicode string

  unicode.script_encoding
= utf-8

  $uni
= "Atildel"; // also Unicode string

  您还可以将 declare() 语句作为 PHP 脚本的第一个语句,这样也可以设置脚本的编码。declare() 构造器覆盖 php.ini 设置。declare() 设置不会传播到文件。  

   unicode.script_encoding = utf-8

  declare(encoding
="iso-8859-1");

  $uni
= "Atildel";// read as ISO-8859-1 string

  include
"inputfile.php";// file is read as UTF-8

  unicode.output_encoding 配置选项指定标准输出流所使用的编码,包括 echo、print 和 var_dump() 函数。输出流的编码被即时转换。unicode.output_encoding 配置选项不影响二进制字符串。  

   unicode.output_encoding = utf-8

  unicode.script_encoding
= iso-8859-1

  $unicode
= "Atildel"; // Unicode string (from ISO-8859-1)

  echo $unicode;
// converts $unicode to UTF-8 encoding

  echo b
"Atildel"; // no conversion, raw contents

  如果启用了 Unicode 语义,HTTP 输入必须转换为 Unicode。GET 请求没有编码,并且也很少指定 POST 请求的编码。PHP V6 提供 unicode.http_input_encoding 配置选项来指定将 HTTP 输入转换为哪种 Unicode 编码。例如,将 HTTP 输入转换为 UTF-8:

 

  unicode.http_input_encoding = utf-8

  PHP 将尝试根据 unicode.http_input_encoding 设置进行解码。如果解码失败,PHP 将使用原始的二进制数据填充请求数组。unicode.filename_encoding 配置选项指定文件系统上文件和目录名的编码。

 

  unicode.filename_encoding = utf-8

  当输入和输出文件名时,与文件系统相关的函数执行所需的转换。PHP V6 提供 unicode.fallback_encoding 配置选项来指定 fallback 编码。

 

  unicode.fallback_encoding = iso-8859-1

  当没有给其他编码分配值时,将使用 fallback 编码。fallback 编码的默认值是 UTF-8。在 PHP V6 中,您可以使用不同的字符编码;当启用 unicode.semantics 选项时,PHP V6 将所有字符串字面量转换为 Unicode 字符串。您可以无缝地对输入和输出使用不同的字符。PHP V6 根据 php.ini 中指定的配置选项对 HTTP 输入和输出进行编码。数据库和用户代理程序能够收到所需的字符编码,而不需使用任何转换函数。

  您不一定要使用 Unicode 开发脚本来处理和输出 Unicode,但我们推荐这么做。如前所述,通过 unicode.script_encoding 配置选项指定脚本编码。为了在数据中(比如 MySQL)存储 Unicode 数据,数据库不需要配置为 UTF-8 编码,但这样做比较好。MySQL 数据库被配置为运行不同的字符集,PHP V6 将以 Unicode 编码发送查询,而 MySQL 将尝试转换它。

  两种字符串类型

  PHP V5 的字符串类型实现有很多字符串类型(二进制、字符串和 Unicode),并且有很多内部引擎函数和帮助函数的实现。PHP V6 只有两种字符串类型:二进制和 Unicode。unicode.semantics 转换(switch)决定字符串字面量的默认类型。如果启用了 unicode.semantics,默认的字符串字面量就为 Unicode。如果禁用该语义转换,默认字符串字面量的类型就为二进制。您可以显式地在 Unicode 和二进制字符串类型之间转换,也可以隐式地进行转换。使用 unicode.runtime_encoding 配置选项进行隐式转换。表 1 显示了如何进行显式转换。

  表 1. 转换字符串类型  

  PHP V6 在内部使用 IS_STRING 表示二进制字符串数据,以及使用 IS_UNICODE 表示 Unicode 字符串数据。

  在扩展中支持 Unicode

  PHP V6 包含了 Unicode/API,扩展可以借助它实现 Unicode 支持。需要向扩展模块结构添加一个标志,以表明它是否支持 Unicode。如果扩展不支持 Unicode,并且在 PHP 中启用了 Unicode 语义,那么在启动时将不加载它。Unicode 支持被添加到 PHP 数据对象中 (PDO)。

  ICU 库

  International Components for Unicode (ICU) 是一组提供 Unicode 和全球化支持的库。PHP V6 需要使用 ICU,但 ICU 是一个大型的库,将增加 PHP 的下载体积。PHP 要求使用 ICU V3.4,并且要求发布版提供 ICU 库。

  文件名编码

  不同的文件名可能使用不同的字符集进行编码。例如,Windows 文件名使用 UTF-16 编码。filename_encoding 设置指定期望的文件名编码。当 read 函数(比如 readdir() 和 readfile())遇到其编码在 filename_encoding 中不存在的文件名时,将返回一个二进制字符串。

  缓存校对器

  校对器(Collator)用于比较字符串。打开和关闭校对器需要引入开销。PHP V6 缓存了校对器,但限制存储在缓存中的对象数量,以防止使用过多的内存。PHP V6 在线程/进程通用缓存中存储最近打开的 3 个校对器。

  基于位置的函数

  对于使用系统位置的 PHP 函数,由于位置名在不同的平台中不一致甚至不可用,因此这是一个问题。PHP V6 仅在合适的地方使用基于位置的函数。基于位置的函数包括 strtoupper/strtolower 和 stristr 等。strtoupper 函数将字母表中的字符都转换为大写的。“字母表的字符顺序” 由当前的位置决定。

  字符集转换错误

  在字符编码之间执行转换可能发生转换错误,因为并不是源字符串中的所有字符都有必要存储在目标字符串中。PHP V6 为字符集转换失败提供一个额外的错误模式,它会在失败时抛出异常。PHP V6 为处理转换错误引入了两个新的 php.ini 配置选项:unicode.from_error_mode 和 unicode.from_error_subst_char。

  unicode.from_error_mode = U_INVALID_SUBSTITUTE

  unicode.from_error_subst_char = 3f

  unicode.from_error_subst_char 选项为无效的字符串指定了代替字符串的十六进制值;它的默认值是 3f。

  unicode.from_error_mode 选项指定错误模式,它在遇到无效字符串时采取行动。表 2 显示了 unicode.from_error_mode 可能使用的值。

  表 2. unicode.from_error_mode 值

  删除了几个函数

  这个小节概述了在 PHP V6 中删除的几个函数。

  删除了 register_globals

  PHP V5 在 php.ini 中使用 register_globals 配置选项从环境和 HTTP 请求参数定义变量。不过,register_globals 生成不安全的代码。因此,在 PHP V6 中删除了 register_globals。

  register_globals 生成不安全代码的方式之一是 authenticate.php,它使用 $auth 变量对用户进行身份验证。因为 $auth 没有被初始化,所以它的值可能通过使用 register_globals 注入变量来定义,比如 GET authenticate.php?auth=1。  

if (authenticated_user()) {

  $auth
= true;

  }

  
if ($auth) {

  include
"/data.php";

  }

  ?
>

  register_globals 注入的变量也可能在会话中生成不安全的代码。看看以下代码,当设置了 $username 变量时,将在用户会话中显示一条欢迎消息。但是,当启用 register_globals 时,可能会使用 HTTP 请求参数注入 $username 变量。  

 if (isset($_SESSION['username'])) {

  echo
"Welcome {$_SESSION['username']}";

  }
else {

  echo
"Welcome Guest";

  }

  ?
>

  所有使用 register_globals 的函数都被删除了,比如 session_register。如果需要导入请求变量,可以使用 import_request_variables。或者使用 $_POST、$_GET、$_COOKIE 和 $_REQUEST 变量。如果设置了 register_globals,PHP V6 将在启动时抛出 E_CORE_ERROR。

  删除了 magic_quotes

  在 PHP V5 中,当启用了 magic_quotes 配置选项时,它会在输入数据中自动将所有单引号(')、双引号(")、反斜杠(\)和 NULL 字符转义为带反斜杠的(\)PHP 脚本。Magic Quotes 减少了 SQL 注入(一种能够篡改 SQL 命令的技术)的风险。Magic Quotes 便于将数据插入到数据库中。不 使用 Magic Quotes 的理由是考虑到移植性、性能和方便性。

  您需要知道是否关闭了 Magic Quotes。如果 Magic Quotes 处于 on,而您认为它处于 off,应用程序就会出现额外的斜杠。如果 Magic Quotes 处于 off,而您认为它处于 on,应用程序就可能遭受 SQL 注入攻击。Magic Quotes 会损害性能,因为并不是所有转义数据都被插入到数据库。一个更好的代替办法是在运行时使用转义函数,比如 addslashes。Magic Quotes 可能带来不便,因为并不是所有数据都需要转义。可以使用 stripslashes 函数删除多余的斜杠。

  PHP V6 不再支持 magic_quotes、magic_quotes_sybase 和 magic_quotes_gpc 设置。如果在启动时发现这些设置,PHP 将发出一个 E_CORE_ERROR。此外,还删除了 get_magic_quotes_gpc() 函数。

  删除了 safe_mode

  在 PHP V5 中,safe_mode 配置选项可用于解决与共享服务器有关的安全问题。它确保需要打开或包含的文件的用户必须与执行这些文件的脚本的用户相同。safe_mode 并不是绝对安全的。

  考虑这样一个场景,一个应用程序使用 Web 服务器的 ID 并生成缓存文件或映像。如果该应用程序由客户机用户加载,PHP 脚本将不能打开缓存文件或映像,因为用户 ID 不匹配。并且,safe_mode 可以绕过库。

  在 PHP V6 中删除了 safe_mode 选项。如果检测到 safe_mode 设置,将抛出 E_CORE_ERROR。open_basedir 配置仍然可用,它限制 PHP 可以在特定目录树中打开的文件。

  删除不赞成使用的行为

  在 PHP V6 中删除了一些在早期的 PHP 版本中不赞成使用的行为。allow_call_time_pass_reference 配置指定在运行时通过引用传递参数时是否发出警告,它在 PHP V5 中就不推荐使用。在 PHP V6 中删除了 allow_call_time_pass_reference。

  如果要指定哪个参数是通过引用传递的,更好的方法是使用声明函数。在 PHP V6 中,call-time-pass-by-reference 将抛出一个 E_STRICT 错误。在 PHP V6 中,“var” 已经成为 “public” 的别名,并且删除了 E_STRICT 警告。受 "new lt;object-name>" 的影响,也删除了 return-by-reference。通过引用赋值 “new” 将抛出一个 E_STRICT 错误。例如,下面的语句将抛出 E_STRICT 错误:

<?php $classA =& new ClassA();?>

  删除了 zend.ze1_compatibility_mode

  zend.ze1_compatibility_mode 配置启用了与 Zend Engine V1 (PHP V4) 的兼容性,它是在 PHP V5 引入的,方便了从 PHP V4 迁移到 PHP V5。

  在 PHP V6 中,已经删除了 zend.ze1_compatibility_mode 特性,如果检测到该设置,将抛出 E_CORE_ERROR。

  删除了 Freetype 1 和 GD 1 库

  FreeType 1 和 GD 1 是老版本的字体呈现和图像处理库。它们不再受到维护,并且已被更新版本的 FreeType 和 GD 代替。在 PHP V6 中,删除了对 FreeType 1 和 GD 1 库的支持。

  默认情况下不启用 dl()

  dl (string $library) 函数用于在运行时加载 PHP 扩展。在 PHP V5 中,可以在 php.ini 配置文件中启用或禁用 dl() 函数:enable_dl = On。

  dl() 函数会给从未加载过的模块带来问题。dl() 函数不能在多线程服务器中正常工作,比如 IIS 或 Zeus,因为在这些服务器中会自动禁用它。不过 dl() 函数在 PHP Command Line Interface (CLI) Server Application Programming Interface (SAPI) 中非常有用。

  在 PHP V6 中,dl() 函数在默认情况下是禁用的,但并没有删除它。SAPI 层可能会显式地注册 dl() 函数。

  FastCGI 模式

  FastCGI 提供很高的性能,如果禁用,将导致杂乱的代码。在 PHP V6 中不能禁用 FastCGI。

  删除了 register_long_arrays

  当启用 register_long_arrays 配置选项时,将注册很长的超级全局变量 — $HTTP_*_VARS 变量。$HTTP_*_VARS 变量是在 PHP V5 中为了向后兼容性而引入的,但不是必要的。使用更短的变量 $_GET、$_POST 和 $_SERVER 代替它会更好。在新的 PHP 版本中,register_long_arrays 设置和 $HTTP_*_VARS 没有得到好评。

  在 PHP V6 中,删除了 register_long_arrays 设置和 $HTTP_*_VARS 全局变量,如果检测到 register_long_arrays,将抛出 E_CORE_ERROR。

  删除 break $var

  动态的 break 操作数不起作用,如以下示例所示:

 

  for (..) { $var = rand(1, 2); break $var; }

  在 PHP V6 中,删除了动态的 break 操作数。取而代之的是,您可以为 $var 分配一个数字,如下所示:

  for (..) { $var = rand(1, 2); break 1; }

  改进扩展

  扩展是 PHP 的主要组件。在 PHP V6 中,有几个组件得到了改进。

  包含在核心发布版中的 XML 扩展

  XMLReader 扩展提供一个 XML 解析器,用于阅读 XML 文件,该解析器在内部基于 SAX 解析。XMLWriter 为写 XML 文件提供一个 API。XMLReader 和 XMLWriter 使 XML 文件的读写更加容易。PHP V5 的核心发布版没有包含 XMLReader 和 XMLWriter。

  PHP V6 将在核心发布版中包含 XMLReader 和 XMLWriter 扩展,并且默认启用这两个扩展。

  正则表达式扩展

  PHP V5.x 为正则表达式提供两个库:ereg 和 Perl Compatible Regular Expression (PCRE)。ereg 库支持 Portable Operating System Interface (POSIX) 正则表达式,而 PCRE 扩展支持与 Perl 兼容的语法。打包的 ereg 库会造成问题,因此被转换成扩展并从核心发布版移动到 PHP Extension Community Library (PECL)。

  PCRE 扩展提供更多的特性,并且比 ereg 扩展快。PCRE 扩展在默认情况下是启用的,并且不可以禁用它。一些核心的 PHP 函数使用 POSIX 正则表达式。因为删除了 ereg 库,所以这些函数将使用 PCRE 表达式重新编写。PCRE 表达式提供一些与 ereg 库等效的函数。

  表 3. PCRE 扩展中的等效函数  

  MIME 类型检查扩展

  在 PHP V5 中,mime_magic 扩展用于媒体类型(media-type)检测,但不是很可靠。PECL 为 MIME 类型检查提供另一个扩展:Fileinfo。mime_magic 扩展将从核心发布版移动到 PECL。Fileinfo 扩展将添加到核心发布版,并默认启用。

  默认启用 SOAP 扩展

  SOAP 扩展(ext/soap)用于开发使用 Web 服务的 PHP 应用程序,包括 SOAP 服务器和 SOAP 客户机。在 PHP V5 中,SOAP 扩展不是默认启用的;开发人员必须配置 SOAP 扩展。在 PHP V6 中,默认启用 SOAP 扩展。PHP V6 还实现一些安全扩展。

  引擎的添加内容

  在 PHP V6,将添加 64 位的整数,同时保留 32 位整数。64 位引擎的转换名为 int64。将使用一个静态标签扩展 break 关键字。将从 ?: 操作符丢弃中间参数。例如,在下面的表达式中,如果 $_GET['var'] 计算为 true,则 $var 设置为 3。如果 $_GET['var'] 计算为 false 或没有设置,则 $var 设置为 $_GET['var']。

 

  $var = $_GET['var'] ?: 3;

  如果 $_GET['var'] 没有设置,将抛出 E_NOTICE。PHP V6 将规定对多维数组使用 foreach 语法。  

$a = array(array(1, 2), array(3, 4));

  foreach( $a
as $k => list($a, $b)) {}

  ?
>

  在 PHP V5 中,{} 和 [] 都可用于访问字符串和数组元素中的字符。在 PHP V6 中,将删除 {},并且继续使用 [],而 [] 操作符将支持 substr()/array_slice() 函数。在 PHP V6 中,microtime() 在默认情况下返回一个浮点值。  

  OO 函数

  在 PHP V6 中对 OO 函数进行了一些改进。添加了关键字 static:: 用于延迟静态绑定,这意味着将执行运行时静态数字计算。

  支持名称空间

  PHP V5 不支持名称空间,而是在一个全局名称空间中定义所有函数和变量。PHP V6 通过关键字 namespace 添加对名称空间的支持。为了定义一个已经定义的类名或函数名,必须使用名称空间将新的类或函数与已经存在的类或函数区分开来。XMLReader 是一个已经存在的类,但是假设您仍然想定义另一个 XMLReader。您应该这样定义 XMLReader 类:  

 namespace XmlNamespace { class XMLReader { }}

  $reader
= new XmlNamespace\XMLReader();

  $reader2
= new XMLReader();

  ?
>

  为了在 XmlNamespace 中调用 XMLReader 类,需要使用前缀 XmlNamespace\。名称空间中可以包含类和函数,但不能包含变量。

  支持类型提示返回值

  PHP V5 仅支持类型提示(其中定义了类型)参数。PHP V6 支持类型提示返回值。

  静态和动态方法调用

  在 PHP V5 中,可以对方法进行静态或动态调用,而不管它是否标记为 static。例如,在下面的清单中,进行了静态和动态方法的调用:  

    class classA { static function aStatic() { echo "static function\n"; }

  
function bDynamic() { echo "dynamic function\n"; }}

  classA::aStatic(
"static call");

  classA::bDynamic(
"static call");

  $classA
= new classA;

  $classA
->aStatic("dynamic call");

  $classA
->bDynamic("dynamic call");

  ?
>

  在 PHP V6 中,使用静态调用语法调用动态函数将抛出一个 E_FATAL 错误,反之亦然。    

  PHP 的添加内容

  opcode 缓存改善了性能。另一个 PHP cache(APC)扩展曾经使用过一段时间,它也将添加到核心 PHP 发布版。默认情况下将不启用 APC 扩展。提供其他安全性的 Hardened PHP 补丁的一些特性已经合并到 PHP。

  现在,许多 PHP 扩展甚至对可修复错误使用 E_ERROR。E_ERROR 终止脚本的运行。因此,在 PHP V6 中,扩展中仅对不可修复的错误使用 E_ERROR。E_STRICT 错误表明这是语言级别的警告或错误,目前还没有包含在 E_ALL 中。在 PHP V6 中,已经将 E_STRICT 添加到 E_ALL。在 PHP V6 中,将为 PHP 添加 MySQL 原生驱动器。并且添加对大于 2 GB 的文件的支持。

  在 PHP V6 中,将删除 ASP 样式的标记 ()。但会保留 PHP 短标记 ()。

  结束语

  本文介绍了 PHP V6 中的新特性和已更改的特性。其中最主要的特性就是对 Unicode 的支持。删除了一些配置选项,比如 register_globals、magic_quotes、safe_mode 和 register_long_arrays。改进了扩展支持和 OO 函数。PHP V5.3 支持 PHP V6 的 50% 的特性。

0
相关文章