初步了解 PHP V6 中的新特性:增强对 Unicode 的支持


简介

  “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. 转换字符串类型
类型转换 描述
(binary) 转换到二进制字符串类型
(unicode) 转换到 Unicode 字符串类型
(string) 如果 unicode.semantics 设置为 on,就转换到 Unicode 字符串类型,否则转换到二进制字符串类型


  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 值
常量 值 说明
U_INVALID_STOP 0 遇到第一个无效字符时停止
U_INVALID_SKIP 1 跳过无效字符
U_INVALID_SUBSTITUTE 2 替换无效字符;默认值
U_INVALID_ESCAPE 3 对无效字符进行转义


  删除了几个函数

  这个小节概述了在 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 注入变量来定义,比如 GETauthenticate.php?auth=1。

<?php 
if (authenticated_user()) { 
  $auth = true; 
} 
if ($auth) { 
  include "/data.php"; 
} 
?> 

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

<?php 
if (isset( 初步了解 PHP V6 中的新特性:增强对 Unicode 的支持 - 站长学院

初步了解 PHP V6 中的新特性:增强对 Unicode 的支持

2010-12-28 17:58:00查看学习心得
{GetProperty(Content)}
« 
» 

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3