PHP字符串实现为指定字节数组和缓冲区长度的整数。没有关于如何将字节转换为字符的信息。决定取决于程序员。组成字符串的值不受限制;特别是,值为0的字节(“NUL字节”)可以放置在字符串的任何位置(但是,在本手册中,“非”binary“”safe“可能忽略NUL字节之后的所有数据)。
字符串类型的此功能解释了为什么PHP没有单独的“字节”类型。取而代之的是字符串。返回非文本值(如从网络套接字读取的任何数据)的函数将继续返回字符串。
因为PHP没有指定字符串的编码,所以字符串是如何正确编码的呢?例如,字符串“á”可以是“xE1”(ISO-8859-1)、“xC3xA1”(UTF-8,C格式)、“x61xCCx81”(UTF-8,D格式)或其他可能的表示?答案是字符串使用与脚本文件相同的编码进行编码。因此,如果脚本编码为ISO-8859-1,则脚本中的字符串也将编码为ISO-8859-1。如果已启用Zend Multibyte,则此选项不适用;然后,脚本以任何方式(显式指定或自动检测的方式)编码,转换为内部编码,字符串以这种方式编码。请注意,脚本编码有一些限制(如果Zend Multibyte处于活动状态,则内部编码)-这意味着该编码必须是兼容的ASCII(如UTF-8或ISO-8859-1)的超级集合。但是,请注意,状态依赖性编码可能会导致问题,该编码允许使用相同的字节值在初始化和非初始化之间切换状态。
当然,为了使使用文本的函数有用,必须假定字符串是如何编码的。不幸的是,PHP有很多用于此的函数。
某些函数假定字符串编码为一个字节,但不需要将字节解释为特定字符。例如,substr()、strpos()、strlen()和strcmp()。了解这些函数的另一种方法是作用于内存缓冲区。也就是说,它从字节和字节索引的角度运行。
某些函数会传递字符串编码,并且默认情况下会认为该信息不存在。例如,htmlentities()和mbstring扩展的大多数函数。
其他函数使用当前区域设置(请参见setlocale()),但以字节为单位工作。例如,strcasecmp()、strtoupper()和ucfirst()。也就是说,这些函数只能用于单字节编码,编码必须与语言环境匹配。例如,如果语言环境设置正确,并且“á”是一个字节编码,则strtoupper(“á”)返回“MAMA”。如果用UTF-8编码,则不返回正确的结果,并且根据当前语言环境,可能返回结果已损坏的值。
最后一些函数假定字符串是特定编码(通常为UTF-8)。这适用于intl展开和PCRE(仅当上面的示例使用u修饰符时)展开的大多数函数。这是出于其特殊目的,但utf8_decode()假定为UTF-8编码,并且utf8_encode()假定为ISO-8859-1编码。
最终,要创建正确使用Unicode的程序,必须谨慎避免可能损坏数据的函数。要使用intl和mbstring扩展函数,请执行以下操作:。但是,使用能够处理Unicode编码的函数只是一个开始。了解Unicode规范是必不可少的,而不管它是用哪种语言提供的。例如,只假定大小写的程序是错误的。