php - 方法、常量、变量和字段的奇异名称 - 错误还是功能?

标签 php unicode

在评论中有些困惑之后

我以为我在做一个问题。根据 PHP 手册,有效的类名应与 [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* 匹配。但显然,这不是强制执行的,也不适用于其他任何事情:

define('π', pi());
var_dump(π);

class ␀ {
    private $␀ = TRUE;
    public function ␀()
    {
        return $this->␀;
    }
}

$␀ = new ␀;
var_dump($␀ );
var_dump($␀->␀());

工作正常(即使我的 IDE 无法显示␀)。一些博学的人可以为我解决这个问题吗?我们可以使用任何 Unicode 吗?如果是这样,从什么时候开始?并不是说我实际上想要使用A-Za-z_ 以外的任何东西,但我很好奇。

澄清:我不是在使用 Regex 来验证类名,我也不知道 PHP 是否在内部使用它在手册中建议的 Regex。让我(显然还有链接问题中的其他人)感到困惑的是为什么 $☂ = 1 之类的东西可以在 PHP 中使用。 PHP6 被认为是 Unicode 版本,但 PHP6 处于中断状态。但是,如果没有 Unicode 支持,为什么我可以这样做呢?

最佳答案

这个问题开始在标题中提到了类名,但接下来是一个例子,其中包括方法、常量、变量和字段的奇异名称。这些实际上有不同的规则。让我们从不区分大小写的开始。

不区分大小写的标识符(类和函数/方法名称)

此处的一般准则是仅使用可打印的 ASCII 字符。原因是这些标识符被规范化为它们的小写版本,但是,这种转换是依赖于语言环境的。考虑以下以 ISO-8859-1 编码的 PHP 文件:

<?php
function func_á() { echo "worked"; }
func_Á();

这个脚本行得通吗?也许。这取决于什么 tolower ( 193 ) 将返回,这取决于语言环境:

$ LANG=en_US.iso88591 php a.php
worked
$ LANG=en_US.utf8 php a.php

Fatal error: Call to undefined function func_Á() in /home/glopes/a.php on line 3

Therefore, it's not a good idea to use non-ASCII characters. However, even ASCII characters may give trouble in some locales. See this discussion. It's likely that this will be fixed in the future by doing a locale-independent lowercasing that only works with ASCII characters.

In conclusion, if we use multi-byte encodings for these case-insensitive identifiers, we're looking for trouble. It's not just that we can't take advantage of the case insensitivity. We might actually run into unexpected collisions because all the bytes that compose a multi-byte character are individually turned into lowercase using locale rules. It's possible that two different multi-byte characters map to the same modified byte stream representation after applying the locale lowercase rules to each of the bytes.

Case-sensitive identifiers (variables, constants, fields)

The problem is less serious here, since these identifiers are case sensitive. However, they are just interpreted as bytestreams. This means that if we use Unicode, we must consistently use the same byte representation; we can't mix UTF-8 and UTF-16; we also can't use BOMs.

In fact, we must stick to UTF-8. Outside of the ASCII range, UTF-8 uses lead bytes from 0xc0 to 0xfd and the trail bytes are in the range 0x80 to 0xbf, which are in the allowed range per the manual. Now let's say we use the character "Ġ" in a UTF-16BE encoded file. This will translate to 0x01 0x20, so the second byte will be interpreted as a space.

Having multi-byte characters being read as if they were single-byte characters is, of course, no Unicode support at all. PHP does have some multi-byte support in the form of the compilation switch "--enable-zend-multibyte" (as of PHP 5.4, multibyte support is compiled in by default, but disabled; you can enable it with zend.multibyte=On in php.ini). This allows you to declare the encoding of the the script:

<?php
declare(encoding='ISO-8859-1');
// code here
?>

它还将处理 BOM,用于自动检测编码并且不会成为输出的一部分。但是,也有一些缺点:

  • 内存和 CPU 性能都受到了影响。它以内部多字节编码存储脚本的表示形式,这会占用更多空间(而且它似乎也在内存中存储原始版本),并且还会花费一些 CPU 来转换编码。
  • 通常不会编译多字节支持,因此测试较少(错误较多)。
  • 编译支持和不编译支持的安装之间存在可移植性问题。
  • 仅指解析阶段; 没有解决不区分大小写标识符的问题。

最后,还有缺乏规范化的问题——同一个字符可能用不同的 Unicode 代码点表示(与编码无关)。这可能会导致一些非常难以跟踪的错误。

关于php - 方法、常量、变量和字段的奇异名称 - 错误还是功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3417180/

相关文章:

javascript - 如何在一组(类)或一组字符中包含多个 Unicode 范围?

javascript - 如何在 React 中将 Unicode 字符作为函数参数传递

以 Unicode 字符作为分隔符的 PHP Explode

javascript - 如何防止页面重定向但仍然提交表单

php - 如何创建一个对大型动态数据集中的标签进行计数的性能系统

php - 在 Ubuntu Amazon EC2 上安装 PhP curl

javascript - URL 重定向未从正确的相对来源加载资源

unicode - 如何使用 Unicode 进行 SEO?

vb.net - 如何从字符串中删除空字符(零字符)

PHP imap 通过代理