我可以在我的脚本中使用UTF-8字符.
事实上,变量和函数的名称可能包含Unicode字符.
还有mb_string扩展,它处理多字节字符串,但在无数文章中,PHP因其缺乏Unicode支持而受到批评.
我不明白; 为什么PHP说不支持Unicode?
几年前PHP启动时,UTF-8并不真正支持.我们谈论的是像Windows 98/Me这样的非Unicode操作系统仍处于当前状态,而其他大型语言(如Delphi)也是非Unicode的时候.从第1天开始,并非所有语言都设计为使用Unicode,并且在不破坏大量内容的情况下将语言完全更改为Unicode非常困难.例如,Delphi仅在一两年前就变成了Unicode兼容,而其他语言如Java或C#则是从第1天开始用Unicode设计的.
因此,当PHP增长并成为PHP 3,PHP 4和现在的PHP 5时,根本没有人决定添加Unicode.为什么?大概是为了与现有脚本保持兼容,或者因为utf8_de/encode和mb_string已经存在并且正常工作.我不确定,但我坚信这与有机增长有关.默认情况下,功能不仅仅存在,它们必须由某人编写,而这对PHP来说根本就不会发生.
编辑:好的,我读错了.问题是:如何在内部存储字符串?如果我输入"Währung"或"Écriture",哪个编码用于创建使用的字节?在PHP的情况下,它是带有代码页的ASCII.这意味着:如果我使用ISO-8859-15对字符串进行编码,并使用一些中文代码页对其进行解码,则会得到奇怪的结果.替代方案是使用C#或Java等语言,其中所有内容都存储为Unicode,这意味着:不再有代码页,理论上你不会搞砸.我推荐乔尔的文章 关于Unicode和字符集,但基本上它归结为:如何在内部存储字符串,而PHP的答案是"不在Unicode中",这意味着在处理字符串时必须非常小心和明确,以确保始终在输入,存储(数据库)和输出期间保持字符串的正确编码,这是非常错误的.
我认为这主要是文化上的困难,而不是技术上的困难.
至于技术问题---在基于"一个字符等于一个字节"的假设构建的生态系统中实现unicode并不是一件容易的事情 - 开发人员可能已经复制了大部分java或python的工作(后者)从2001年左右开始,它具有良好且大部分工作的unicode兼容性,但他们从未这样做过.
当我阅读附加到官方的讨论主题,当前的php utf8_encode()
函数文档时,我感到眩晕.
firstoff,调用该函数utf8_encode()
; 但是,文档声明它预期的字符串应该是ISO-8859-1(又名latin-1).这是sooo php,那是80年代的sooo.
大多数评论者似乎认为unicode是一种负担.有很多建议如何转换未知内容的字符串,如何处理混合编码的字符串(wtf?),或处理通常导致破坏的代码点,因为它们超出了该函数的四个字节代码点限制.
讨论以修正为中心,以摆脱曲线或避免该函数行为的问题部分.而且,对我来说,是sooo php:每个人都在做修复,很少有东西是以一种基本正确的方式实现的.如果你认为这是我的诽谤,这里有一些花絮:
虽然如果该文件已经是UTF-8,这似乎打破了德国的Umlaute [äöü].
(无法理解utf-8在两次应用时不适用)
看看iconv()函数,它提供了一种从8859和可怕的1252转换为UTF8的方法
(好点:部分php开发人员忽略了现有技术;相反,错误自己的实现)
使用preg_match来检测是否需要utf8_encode [...],不包括替代品[...]
(建议从字符串中默默地删除所有有问题的内容,只留下那些不会中断的内容utf8_encode()
;这可能会使文本无法读取(或完全消失),但是,嘿,没有更多错误消息)
仅在字符串不是UTF-8时对其进行编码[...]
mb_detect_encoding($s, "UTF-8")
(正如另一位评论者指出的那样,这不会起作用:
$str = 'áéóú'; // ISO-8859-1 mb_detect_encoding($str, 'UTF-8'); // 'UTF-8' mb_detect_encoding($str, 'UTF-8', true); // false
所以我们在这里看到一个被另一个错误替换的错误.快乐狩猎.此外,他们似乎在这里提出的是使用启发式(缓慢,不确定)来解决问题,这意味着可以并且应该通过机械(快速,确定)手段解决)
utf8_ [encode | decode]实际上也会翻译windows-1252字符,而不仅仅是来自/到ISO-8859-1,正如文档说的那样
(你不能依赖官方的php文档清晰或详尽 - 你必须经常阅读多年的用户体验,没有人会反馈给文档)
我一直在研究is_utf8函数并想在这里发布,除了其他我还考虑了5000 char bug
(一个很大程度上只存在因为unicode没有正确实现的问题的修复.我们还了解到,utf8_encode()
每个代码点的函数不仅会超出4个字节,如果结果(或输出?)文本超出限制,它也会中断5000个字符)
我可以继续这样下去.你已经明白了这一点:从这个线程判断,php社区听起来并不像他们在任何地方都准备好了解编码和字符集的全部内容,一般来说构建一个完善的基础设施需要什么,或者特别是以适当的方式实现unicode.相反,他们正在使用他们的脚手架,他们的纸板,他们的钉子和锤子,继续建造这个名为php的宏伟大厦,将他们的胶带扔在每一个用另一个钉子无法解开的问题上.当然,这座建筑将遭受每一次吹来的风,例如偶尔合法但意外的性格.
看到这个特殊的线程活跃了八年并没有完全灌输信心,从现在起八年内情况会好转.
"多字节字符"的概念是问题的核心.
它漏掉了一个实现细节:你应该能够在不知道实现者如何选择表示数据的情况下处理角色的抽象 - 可能取决于它适合它们的平台,将所有东西表示为UTF16或UTF32,在这种情况下,一切都是多字节,而不是字符抽象的用户应该关心.
它是一个kludge:除了过时的思维习惯,我们都"真的知道"字符串是字节序列,我们现在必须知道有时字节聚集成称为Unicode字符的东西,并且有特殊的各地的案件来处理它.
它就像一只试图吃大象的老鼠.通过将Unicode构建为ASCII的扩展(我们有普通字符串并且我们有mb_strings),它会以错误的方式解决问题,并且需要处理需要多个字节的有趣曲线所需的特殊情况.如果您将Unicode视为为您需要的任何字符提供抽象空间,则可以使用ASCII,而无需将其视为特殊情况.
你自己说:为了正确处理包含多字节字符的字符串,你需要使用扩展名.忘记在任何地方使用扩展功能而不是更熟悉的"普通"功能,并且您的数据被肢解.如果您使用尚未更新的第三方库在任何地方使用扩展功能,也会发生同样的情况.
此外,PHP 仍然明确不支持许多非常流行的编码,大概是因为它不可能这样做并且保持向下兼容.