# UTF-8:字符编码的秘密
[http://htmlpurifier.org/docs/enduser-utf8.html#findcharset](http://htmlpurifier.org/docs/enduser-utf8.html#findcharset)
## 寻找真实的编码
最初是ASCII,事情很简单。但是它们不好,因为没有人能用西里尔文或泰文写作。因此,爆炸了字符编码,以扩展ASCII可以表示的字符来解决该问题。字符编码历史的这个荒谬的简化版本向我们表明,现在有许多字符编码在浮动。
> 一个**字符编码**告诉计算机如何解释原始零和一成真实人物。通常通过将数字与字符配对来实现。
>
> 周围有许多不同类型的字符编码,但是我们最常处理的是ASCII,8位编码和基于Unicode的编码。
>
> * **ASCII**是基于英文字母的7位编码。
> * **8位编码**是ASCII的扩展,增加了有用的非标准字符(例如é和æ)的杂烩。他们只能添加127个字符,因此通常一次仅支持一个脚本。当您在网络上看到某个页面时,很可能会以其中一种编码方式对其进行编码。
> * **基于Unicode的编码**实现Unicode标准,包括UTF-8,UTF-16和UTF-32 / UCS-4。它们超越了8位,并且支持世界上几乎所有语言。作为网络的主要国际编码方式,UTF-8受到越来越多的关注。
我们旅程的第一步是找出您网站的编码。最可靠的方法是询问您的浏览器:
火狐浏览器
工具>页面信息:编码
IE浏览器
查看>编码:项目符号为非官方名称
Internet Explorer不会为您提供字符编码的MIME名称(即有用/真实),因此您必须使用其描述来查找它。一些常见的:
| IE的描述 | Mime Name |
| --- | --- |
| 视窗 |
| 阿拉伯语(Windows) | Windows-1256 |
| 波罗的海(Windows) | Windows-1257 |
| 中欧(Windows) | Windows-1250 |
| 西里尔文(Windows) | Windows-1251 |
| 希腊文(Windows) | Windows-1253 |
| 希伯来语(Windows) | Windows-1255 |
| 泰语(Windows) | TIS-620 |
| 土耳其语(Windows) | Windows-1254 |
| 越南文(Windows) | Windows-1258 |
| 西欧(Windows) | Windows-1252 |
| ISO标准 |
| 阿拉伯文(ISO) | ISO-8859-6 |
| 波罗的海(ISO) | ISO-8859-4 |
| 中欧(ISO) | ISO-8859-2 |
| 西里尔文(ISO) | ISO-8859-5 |
| 爱沙尼亚语(ISO) | ISO-8859-13 |
| 希腊文(ISO) | ISO-8859-7 |
| 希伯来语(ISO逻辑) | ISO-8859-8-l |
| 希伯来语(ISO-Visual) | ISO-8859-8 |
| 拉丁文9(ISO) | ISO-8859-15 |
| 土耳其文(ISO) | ISO-8859-9 |
| 西欧(ISO) | ISO-8859-1 |
| 其他 |
| 简体中文(GB18030) | GB18030 |
| 简体中文(GB2312) | GB2312 |
| 简体中文(HZ) | 赫兹 |
| 繁体中文(Big5) | 大5 |
| 日语(Shift-JIS) | Shift\_JIS |
| 日语(EUC) | EUC-JP |
| 韩语 | EUC-KR |
| Unicode(UTF-8) | UTF-8 |
Internet Explorer无法识别某些较晦涩的字符编码,因此必须使用表查找实名是很麻烦的,因此,我建议使用Mozilla Firefox来查找您的字符编码。
## 查找嵌入式编码
此时,您可能会问:“我们是否已经找到编码?”事实证明,Web开发人员可以在多个地方指定字符编码,并且在`META`标记中可以找到一个这样的地方:
~~~
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
~~~
您可以在`HEAD`HTML文档的部分中找到此内容。右边的文本`charset=`是“声明的”编码:HTML声称是这种编码,但是实际上是否如此取决于其他因素。现在,请注意您的`META`标签是否声明:
1. 字符编码与浏览器报告的字符编码相同,
2. 字符编码与浏览器的字符编码不同,或者
3. 根本没有`META`标签!(恐怖,恐怖!)
## 固定编码
这里给出的建议是将页面作为普通文本`text/html`。`application/xml`或必须使用不同的做法`application/xml+xhtml`,有关更多信息,请参见[XHTML媒体类型上的W3C文档](http://www.w3.org/TR/2002/NOTE-xhtml-media-types-20020430/)。
如果您的`META`编码和实际编码相符,请机灵!您可以跳过此部分。如果他们不...
### 没有嵌入式编码
在这种情况下,您需要在`META`网站中添加适当的标记。就像复制粘贴上面的代码片段并将UTF-8替换为实际编码的MIME名称一样简单。
> 对于所有那些怀疑者,有一个很好的理由为什么应该明确说明字符编码。当不告知浏览器文本的字符编码是什么时,它必须猜测:有时猜测是错误的。黑客可以操纵这种猜测,以使XSS越过过滤器,然后欺骗浏览器将其作为活动代码执行。[Google UTF-7漏洞](http://shiflett.org/archive/177)就是一个很好的例子。
>
> `META`只要您的网络服务器发送正确的Content-Type标头,您就可以不用指定标签的字符编码就可以摆脱困境,但是为什么要冒险呢?此外,如果用户下载HTML文件,则不再有任何Web服务器来定义字符编码。
### 嵌入式编码不同意
这是一个非常普遍的错误:另一个消息来源是告诉浏览器字符编码是什么,并且覆盖了嵌入式编码。该来源通常是网络服务器(即Apache)发送的Content-Type HTTP标头。与页面一起发送的通常的Content-Type标头可能如下所示:
~~~
内容类型:text / html;字符集= ISO-8859-1
~~~
请注意,这里有一个charset参数:这是Web服务器告诉浏览器字符编码的方式,就像`META`我们之前接触过的标签一样。
> 实际上,对于`META`无法发送标头的上下文(例如,没有Web服务器的本地存储文件),该标签旨在代替HTTP标头。因此,名称`http-equiv`(等效于HTTP)。
解决此问题的方法有两种:更改`META`标签以匹配HTTP标头,或更改HTTP标头以匹配`META`标签。我们如何知道该怎么办?它取决于网站的内容:毕竟,标题和标签只是描述网页上实际字符的方式。
如果您的网站:
...仅使用ASCII字符,
两种方法都可以,但是我建议将两者都切换为UTF-8(稍后再介绍)。
...使用特殊字符,它们可以正确显示,
将嵌入的编码更改为服务器编码。
...使用特殊字符,但用户经常抱怨它们出现乱码,
将服务器编码更改为嵌入式编码。
更改META标签很容易:只需将旧编码换成新编码即可。但是,更改服务器(HTTP标头)编码会稍微困难一些。
### 更改服务器编码
#### PHP header()函数
解决此问题的最简单方法是自己通过编程语言发送编码。由于您使用的是HTML Purifier,因此我假设使用PHP,尽管用[其他语言](http://www.w3.org/International/O-HTTP-charset#scripting)进行类似的操作并不难。合适的代码是:
~~~
标头('Content-Type:text / html; charset = UTF-8');
~~~
...使用您的嵌入式编码替换UTF-8。此代码必须在任何输出之前出现,因此请注意应用程序中的空白(即,输出之前的任何空白,除了标记内的空白)。
#### PHP ini指令
PHP还有一个简洁的ini指令,可以节省您的标头调用:`[default_charset](http://php.net/ini.core#ini.default-charset)`。使用此代码:
~~~
ini_set('default_charset','UTF-8');
~~~
...也可以解决问题。如果PHP作为Apache模块运行(而不是作为FastCGI运行,请查阅[phpinfo](http://php.net/phpinfo)()了解详细信息),您甚至可以使用htaccess在多个PHP文件中应用此属性:
~~~
php_value default_charset“ UTF-8”
~~~
> 与所有INI指令一样,这也可以放在php.ini文件中。一些托管服务提供商允许您自定义自己的php.ini文件,要求您的支持以获取详细信息。采用:
>
> ~~~
> default_charset =“ utf-8”
> ~~~
#### 非PHP
无论出于何种原因,您都可能需要在非PHP文件(通常是普通HTML文件)上设置字符编码。这样做更像是一个命中注定的过程:取决于用作网络服务器的软件和该软件的配置,某些技术可能有效或无效。
#### .htaccess
在Apache上,您可以使用.htaccess文件来更改字符编码。我将参考[W3C](http://www.w3.org/International/questions/qa-htaccess-charset)进行深入的解释,但是归结为创建一个名为.htaccess的文件,其内容如下:
~~~
AddCharset UTF-8 .html
~~~
在将UTF-8替换为您要使用的字符编码的情况下,.html是将应用到的文件扩展名。然后,将直接在您放置此文件的目录中或该目录的子目录中为任何文件设置此字符编码。
如果您感到特别勇气,可以使用:
~~~
添加默认字符集 UTF-8
~~~
...这将更改Apache添加到不具有任何Content-Type参数的任何文档中的字符集。出于安全原因,该指令(默认配置文件将其设置为iso-8859-1)可能是标题与`META`标签不匹配的原因。如果您不希望Apache不参与字符编码,则可以告诉它根本不发送任何内容:
~~~
AddDefaultCharset关
~~~
...使内部字符集声明(通常是`META`标签)成为字符编码信息的唯一来源。在这些情况下,*特别*重要的是要确保您`META`的页面上有有效的标记,并且之前的所有文本均为ASCII。
> 这些指令也可以放在Apache的httpd.conf文件中,但是在大多数共享托管情况下,您将无法编辑此文件。
#### 文件扩展名
如果不允许使用.htaccess文件,则通常可以背负Apache的默认AddCharset声明,以使文件具有适当的扩展名。这是Apache的默认字符集声明:
| 字符集 | 文件扩展名 |
| --- | --- |
| ISO-8859-1 | .iso8859-1 .latin1 |
| ISO-8859-2 | .iso8859-2 .latin2 .cen |
| ISO-8859-3 | .iso8859-3 .latin3 |
| ISO-8859-4 | .iso8859-4 .latin4 |
| ISO-8859-5 | .iso8859-5 .latin5 .cyr .iso-ru |
| ISO-8859-6 | .iso8859-6 .latin6 .arb |
| ISO-8859-7 | .iso8859-7 .latin7 .grk |
| ISO-8859-8 | .iso8859-8 .latin8 .heb |
| ISO-8859-9 | .iso8859-9 .latin9 .trk |
| ISO-2022-JP | .iso2022-jp .jis |
| ISO-2022-KR | .iso2022-kr .kis |
| ISO-2022-CN | .iso2022-cn。顺式 |
| 大5 | .big5 .big5 .b5 |
| WINDOWS-1251 | .cp-1251 .win-1251 |
| CP866 | .cp866 |
| KOI8-r | .koi8-r .koi8-ru |
| KOI8-RU | .koi8-uk .ua |
| ISO-10646-UCS-2 | .ucs2 |
| ISO-10646-UCS-4 | .ucs4 |
| UTF-8 | .utf8 |
| GB2312 | .gb2312 .gb |
| utf-7 | .utf7 |
| EUC-TW | .euc-tw |
| EUC-JP | .euc-jp |
| EUC-KR | .euc-kr |
| shift\_jis | .sjis |
因此,例如,一个名为`page.utf8.html`或的文件`page.html.utf8`可能会附加UTF-8字符集发送,不同之处在于,如果有`AddCharset charset .html`声明,它将覆盖.utf8扩展名`page.utf8.html`(优先级从右移到左)。默认情况下,Apache没有此类声明。
#### Microsoft IIS
如果有人可以提供有关如何配置Microsoft IIS来更改字符编码的信息,我将不胜感激。
### XML格式
`META`标签是最常见的嵌入式编码来源,但它们也可以来自其他地方:XML声明。他们看起来像:
~~~
<?xml版本=“ 1.0”编码=“ UTF-8”?>
~~~
...并且最常见于XML文档(包括XHTML)中。
对于XHTML,理论上,此XML声明会覆盖`META`标记。实际上,只有在XHTML实际上是合法的XML而不是HTML时才发生这种情况,这几乎永远不会由于Internet Explorer的缺乏而支持`application/xhtml+xml`(尽管通常认为这样做是一种[很好的做法,](http://www.hixie.ch/advocacy/xhtml)并且XHTML要求这样做)1.1规范)。
但是,对于XML,此XML声明非常重要。由于大多数Web服务器未配置为发送.xml文件的字符集,因此这是解析器唯一要做的事情。此外,XML文件的默认设置为UTF-8,它通常使用更常见的ISO-8859-1编码来对头(您在乱码的RSS提要中看到了这一点)。
简而言之,如果您使用XHTML并遇到了添加XML声明的麻烦,请确保它与您的`META`标签(仅在text / html中提供的标签)和HTTP标头配合使用。
### 流程内部
本部分不是必读部分,但可能会回答您有关所有此字符编码轨迹的最新信息。如果您有兴趣进入下一个阶段,请跳过本节。
我们所有人都在研究并处理多种字符编码源之后,一个逻辑问题是“为什么会有这么多选择?”为了回答这个问题,我们必须回退字符编码的定义:它们允许程序将字节解释为人类可读的字符。
因此,出现了一个鸡蛋问题:必须使用字符编码来解释文档的文本。一个`META`标签是在文档的文本。该`META`标记给出了字符编码。`META`如果我们不知道标记的字符编码,如何确定其内容呢?如果我们不知道`META`标签的内容,我们如何找出字符编码?
对我们来说幸运的是,我们需要编写的字符`META`都是ASCII的,这在当今通常使用的每种字符编码中都非常普遍。因此,网络浏览器所需要做的就是一直解析直到到达Content-Type标记,提取字符编码标记,然后根据此新信息重新解析文档。
显然,这很复杂,因此浏览器更喜欢更简单,更有效的解决方案:从文档本身之外的其他位置(即HTTP标头)获取字符编码,这令无法设置这些标头的HTML作者非常恼火。
## 为什么选择UTF-8?
因此,您已经经历了所有麻烦,以确保服务器和嵌入式字符都正确排列并存在。做得好:在这一点上,您可以知道自己的页面不容易受到字符编码样式XSS攻击的影响,从而退出并轻松自在。但是,就像拥有字符编码比完全没有字符编码要好一样,拥有UTF-8作为字符编码要比具有其他随机字符编码要好,下一步就是转换为UTF-8。但为什么?
### 国际化
许多软件项目在某一时刻突然意识到它们应该支持多种语言。即使是一种语言的常规用法,有时也需要偶尔使用特殊字符,这并不奇怪,您的字符集中没有该特殊字符。有时,开发人员通过添加对多种编码的支持来解决此问题:使用中文时,使用Big5,使用日语时,使用Shift-JIS,使用希腊语等。其他时候,他们使用带有热情的字符引用。
但是,UTF-8消除了对任何这些复杂措施的需要。使系统使用UTF-8并针对浏览器无法控制的源进行调整后(稍后会详细介绍),UTF-8才可以使用。您可以将它同时用于任何一种语言,甚至可以用于多种语言,您不必担心管理多种编码,也不必使用那些对用户不友好的实体。
### 方便使用的
使用Latin-1(ISO-8859-1)编码的网站有时需要超出其范围的特殊字符,通常会使用字符实体引用来达到预期的效果。例如,可以写入θ`θ`,而与希腊字母的字符编码支持无关。
这对于限制使用特殊字符效果很好,但是说您想要这句话的中文文本:激光,这两个字是什么意思。与符号编码的版本如下所示:
~~~
&#28608;&#20809 ;,&#36889;&#20841;&#20491;&#23383;&#26159;&#29978;&#40636;&#24847;&#24605;
~~~
对于我们当中那些真正知道角色实体是什么的人来说,这极为不便,而对于那些不知道这些角色的贫困用户来说,这是绝对无法理解的!甚至像稍微更用户友好的“难以理解”的字符实体,`θ`也会使对学习HTML不感兴趣的用户挠头。另一方面,如果他们在编辑框中看到θ,他们将知道这是一个特殊字符,并对其进行相应处理,即使他们自己不知道如何编写该字符也是如此。
> 对于最初使用ISO-8859-1的应用程序来说,Wikipedia是一个很好的案例研究,但是当它变得繁琐而无法支持外语时,便切换为UTF-8。Bot现在实际上将浏览文章并将字符实体转换为它们相应的真实字符,以便于用户友好和可搜索。有关更多详细信息,请参见[Meta的特殊字符页面](http://meta.wikimedia.org/wiki/Help:Special_characters)。
### 形式
当我们站在用户的立场上时,非UTF-8网络表单如何处理其字符集之外的字符?除了要讨论UTF-8的正确之处,我们还要说明的是如果您不使用UTF-8并且人们尝试使用字符编码之外的字符,那么可能会出问题。
问题很大,范围广泛,而且很难解决(或者至少很难解决,如果您有时间和资源进行修复,那么最好迁移到UTF-8)。表单提交有两种类型:`application/x-www-form-urlencoded`一种用于GET,默认情况下用于POST,并且`multipart/form-data`可以由POST使用,并且在您要上传文件时需要。
以下是[提交和i18n](http://web.archive.org/web/20060427015200/ppewww.ph.gla.ac.uk/~flavell/charset/form-i18n.html)的注释摘要。该文档包含许多有用的信息,但是以粗俗的方式编写,因此在这里我尝试着重点。(注意:原始文件已经从网络上消失了,因此我链接到Web存档副本。)[`FORM`](http://web.archive.org/web/20060427015200/ppewww.ph.gla.ac.uk/~flavell/charset/form-i18n.html)
#### `application/x-www-form-urlencoded`
这是GET请求必须使用的Content-Type,而POST请求默认使用。它涉及到无所不在的百分比编码格式,如下所示:`%C3%86`。由于百分比编码在字节级别上进行操作,因此没有确定这种请求的字符编码的官方方法,因此通常假定它与提交表单的页面的编码相同。([RFC 3986](http://tools.ietf.org/html/rfc3986#section-2.5)建议将文本标识符转换为UTF-8;但是,浏览器兼容性差强人意。)如果仅在选择的字符编码中使用字符,您将遇到很少的问题。
但是,一旦开始在编码之外添加字符(这比您想像的要普遍得多:以Microsoft的卷曲“ smart”引号为例),就会发生各种各样奇怪的事情。根据您使用的浏览器,它们可能:
* 将不支持的字符替换为无用的问号,
* 尝试修复字符(例如:将智能引号替换为常规引号),
* 用字符实体引用替换字符,或者
* 无论如何,以不同的字符编码与原始编码混合发送(通常是Windows-1252,而不是散布在8位中的iso-8859-1或UTF-8)
为了适当地防止这些行为,您必须嗅探浏览器代理,编译具有不同行为的数据库,并对字符串采取适当的转换操作(而不管Internet Explorer每次出现的一系列极其神秘,随机和破坏性的错误)等一下)。或者您可以使用UTF-8并放心,因为UTF-8支持每个字符,所以这一切都不可能发生。
#### `multipart/form-data`
多部分表单提交消除了百分比编码所带来的许多歧义:服务器现在可以显式地请求某些编码,并且客户端可以在表单提交期间显式地告诉服务器字段的编码。
您可以通过两种方法使用此功能:将其保留为未设置状态,然后让浏览器以与页面相同的编码进行发送,或者将其设置为UTF-8,然后在服务器端执行另一次转换。每种方法都有缺陷,尤其是前者。
如果告诉浏览器以与页面相同的编码发送表单,则仍会遇到如何处理超出字符编码范围的字符的麻烦。行为再次有所不同:Firefox 2.0将它们转换为字符实体引用,而Internet Explorer 7.0则使它们难以理解。为了严肃的国际化目的,这不是一个选择。
另一种可能性是将Accept-Encoding设置为UTF-8,这引出了一个问题:您为什么不对所有内容都使用UTF-8?这条路线更可口,但是有一个值得注意的警告:您的数据将以UTF-8格式输入,因此您必须将其显式转换为您喜欢的本地字符编码。
我出于思想上的原因反对这种方法:当您本来可以转换为UTF-8时,您将更深入自己。而且,当然,您不能对GET请求使用此方法。
### 很好的支持
如今,几乎所有狂野的现代浏览器都完全支持UTF-8和Unicode:麻烦的情况可以用一只手的手指来计算,这些浏览器通常也遇到其他字符编码的麻烦。用户通常会遇到的问题是由于缺少合适的字体来显示字符(再一次,这适用于所有字符编码和HTML实体)或Internet Explorer缺乏智能字体选择(可以解决)。
我们将在“迁移”部分中详细介绍如何处理浏览器世界中的一些极端情况,但是请放心,如果正确完成转换,转换为UTF-8不会导致用户困扰您破碎的页面。
### HTML净化器
最后,我们进入HTML Purifier。HTML Purifier是为处理UTF-8而构建的:否则,任何指示都是编码器的结果,该编码器将文本从您的首选编码转换为UTF-8,然后再次转换。HTML Purifier永远不会触碰其他任何东西,而是将其留给模块iconv来完成肮脏的工作。
但是,这种方法并不完美。iconv根本不了解HTML字符实体。为了防止复杂的转义方案,HTML Purifier在处理文本之前将所有字符和数字实体引用标准化。这导致了一个重要的后果:
**目标字符集不支持的任何字符,无论它是以字符实体引用还是原始字符的形式,都将被静默忽略。**
此原则的示例正在起作用:假设您已经`θ`在HTML中使用,但是输出使用的是Latin-1(可以理解,它不理解希腊语),则会发生以下过程(假设您已使用%Core正确设置了编码.Encoding):
* 该`Encoder`会从ISO 8859-1转换文本为UTF-8(注意,theta是保存在这里,因为它实际上并未使用任何非ASCII字符):`θ`
* 在`EntityParser`将改变所有命名和数字字符实体到他们相应的原始UTF-8当量:`θ`
* HTML Purifier处理代码:`θ`
* 在`Encoder`现在将来自UTF-8 ISO 8859-1背课文。由于ISO 8859-1不支持希腊语,因此它将被忽略或替换为问号:`?`
此行为是非常不令人满意的。它是国际应用程序的突破者,对于偶尔需要特殊字符的省级灵魂可能会有些恼火。从1.4.0版本开始,HTML Purifier使用%Core.EscapeNonASCIICharacters提供了稍微更可口的解决方法。现在,该过程如下所示:
* 的`Encoder`编码为UTF-8变换:`θ`
* 该`EntityParser`变换实体:`θ`
* HTML Purifier处理代码:`θ`
* 该`Encoder`替换数字实体引用的所有非ASCII字符:`θ`
* 为了达到良好的效果,请将`Encoder`编码转换回原始`θ`格式(对于99%的编码来说,这绝对是不必要的):(请记住,全都是ASCII!)
...这意味着这仅对偶尔进入Unicode字符领域很有用,而中文或日文文本完全不可接受。更大的缺点是,假设输入编码实际上*是*支持theta的ISO-8859-7,*则*无论如何该字符都将转换为字符实体引用!(编码器不区分)。
当前的功能是关于HTML Purifier在永恒的岁月中所处的位置。HTML Purifier可以尝试保留字符引用的原始形式,以便可以将它们替换回去,只有DOM扩展名不可逆转地将其杀死。HTML Purifier也可以尝试变得聪明,只转换目标编码不支持的非ASCII字符,但这将需要重新实现具有HTML意识的iconv,而我不会这样做。
就是这样:要么是UTF-8,要么是残废的国际支持。您的选择!(而且我这里并不是在讽刺:有些人可能不太在乎其他语言)。
## 迁移到UTF-8
因此,您已经决定硬着头皮,并想要迁移到UTF-8。请注意,这不是为胆小者准备的,您应该期望该过程花费的时间比您认为的要长。
通常的想法是,将所有现有文本转换为UTF-8,然后将我们前面讨论的所有标头和META标记设置为UTF-8。这样做的方法有很多:您可以编写一个转换脚本,该脚本在数据库中运行并将所有内容重新编码为UTF-8,或者当有人阅读该页面时,您可以即时进行转换。详细信息取决于您的系统,但是我将介绍一些可能会使您绊倒的更细微的迁移点。
### 配置数据库
大多数现代数据库(最著名的开源数据库是MySQL 4.1+和PostgreSQL)都支持字符编码。从逻辑上讲,如果要切换到UTF-8,则需要确保数据库也知道该更改。但是有一些警告:
#### 合法方法
用于指定字符编码的SQL语法方面的标准化是众所周知的。有关如何正确执行此操作,请参阅各自数据库的文档。
对于[MySQL](http://dev.mysql.com/doc/refman/5.0/en/charset-conversion.html),`ALTER`将神奇地为您执行字符编码转换。但是,您必须确保该列中的文字是它所说的:如果将Shift-JIS放在ISO 8859-1列中,则当您尝试将其转换为UTF-时,MySQL将不可逆转地处理该文本。 8。您必须将其转换为二进制字段,将其转换为Shift-JIS字段(实际编码),然后最终转换为UTF-8。许多网站的页面不可逆地受到破坏,因为他们没有意识到自己一直在欺骗字符编码;不要成为下一个受害者。
对于[PostgreSQL](http://www.postgresql.org/docs/8.2/static/multibyte.html),似乎没有直接的方法可以更改数据库的编码(从8.2版本开始)。您将必须转储数据,然后将其重新导入到新表中。确保正确设置了客户端编码:这就是PostgreSQL知道执行编码转换的方式。
很多时候,还会询问您新列的“排序规则”。排序规则是DBMS对文本进行排序的方式,例如将B,C和A排序为A,B和C(当您使用泰语和日语等语言时,问题变得异常复杂)。如有疑问,使用默认设置通常是一个安全的选择。
一旦完成所有的转换,您仍然必须记住使用`SET NAMES`(标准SQL,通常支持)在每个数据库连接上正确设置客户端编码(您的编码)。
#### 二元
由于上述兼容性问题,存储UTF-8文本的一种更可互操作的方法是将其填充为二进制数据类型。`CHAR`成为`BINARY`,`VARCHAR`成为`VARBINARY`,`TEXT`成为`BLOB`。这样做可以为您省去很多麻烦:
* 二进制数据类型的语法非常易于移植,
* MySQL 4.0*不*支持字符编码,因此,如果要支持字符编码,则*必须*使用二进制,
* 从5.1版本开始,MySQL不支持四个字节的UTF-8字符,这些字符表示超出基本多语言平面的字符,并且
* 您将永远不必担心DBMS太聪明,并在不需要时尝试转换文本。
MediaWiki是一个非常著名的国际应用程序,由于第三点,它使用二进制字段来存储其数据。
当然也有缺点:
* 由于PHPMyAdmin等数据库工具被声明为二进制文件,因此无法为您提供内联文本编辑功能,
* 这在语义上是不正确的:它实际上是文本而不是二进制文件(位于数据库中),
* 除非您使用上面提到的非便携式向导,否则您必须自己更改编码(通常,您会即时进行编码),并且
* 您将没有排序规则。
根据您的情况选择。
### 文本编辑器
对于面向平面文件的系统,通常会负责将现有文本和HTML文件的一部分转换为UTF-8,并确保所有上传的新文件都经过正确编码。再一次,我只能模糊地指出转换现有文件的正确方向:确保备份,确保使用[iconv](http://php.net/ref.iconv)(),并确保知道文件的原始字符编码是(或取决于)在系统的整洁度上)。
但是,我可以针对文本编辑器提供更具体的建议。众所周知,许多文本编辑器都支持Unicode。要了解编辑器的工作方式,您可以查看[此列表](http://www.alanwood.net/unicode/utilities_editors.html)或[Wikipedia的列表。](http://en.wikipedia.org/wiki/Comparison_of_text_editors#Encoding_support)我个人使用的是Notepad ++,它在使用UTF-8时就像一个魅力。通常,您将必须通过一些对话(通常是“另存为”或“格式”)**明确**告诉编辑器您要使用的编码。编辑器通常会提供“ Unicode”作为保存方法,这是模棱两可的。确保您知道它们是否真正表示UTF-8或UTF-16(这是Unicode的另一种形式)。
需要注意的两件事是编辑器是否支持**字体混合**(一个文档中有多种字体)以及是否添加**BOM**。字体混合非常重要,因为字体很少支持人类已知的每种语言:为了灵活起见,编辑者必须能够从这里一点点拿走一点,否则所有的汉字都将变成漂亮的盒子。我们将在下面讨论BOM。
### 字节顺序标记(标题已发送!)
BOM([字节顺序标记](http://en.wikipedia.org/wiki/Byte_Order_Mark))是一个神奇的,不可见的字符,放置在UTF-8文件的开头,用于告诉人们编码是什么以及文本的字节序是什么。这也是不必要的。
因为它是不可见的,所以当它开始做本不应该做的事情时,常常会让人感到惊讶。例如,此PHP文件:
~~~
BOM <?php
header('Location:index.php');
?>
~~~
...将会因所有过于熟悉的标**头已发送**PHP错误而失败。而且因为BOM是不可见的,所以这个罪魁祸首将不会被注意到。我的建议是仅在PHP页面中使用ASCII,但如果必须的话,请确保在不使用BOM表的情况下保存该页面。
> 错误所指的标头是**HTTP标头**,这些**标头**在发送任何HTML之前先发送给浏览器以告知各种信息。输出任何常规文本(是的,物料清单算作普通文本)后,必须发送标头,并且您再也不能发送了。因此,错误。
如果您正在阅读文本文件以插入到另一页的中间,强烈建议(但并非绝对必要)通过以下方式替换BOM的UTF-8字节序列`"\xEF\xBB\xBF"`:
~~~
$ text = str_replace(“ \ xEF \ xBB \ xBF”,``,$ text);
~~~
### 字型
一般来说,遇到字体问题的人分为两类:
* 那些想要使用一种非常晦涩难懂的语言的人,即使母语为母语的人也几乎没有这种支持,并且
* 那些文字的主要语言得到了很好的支持,但是偶尔不支持这些字符的语言。
是的,在Sinhalese网站上总是有英语使用者出现在网站上,并且字体不正确。但是,碰巧没有正确字体的英语用户可能仍然无法阅读僧伽罗语。因此,我们将处理其他两种情况。
#### 晦涩的脚本
如果您运行孟加拉语网站,则可能会得到那些希望阅读您的网站但收到大量问号或其他无意义字符的用户的评论。要解决此问题,需要安装字体或语言包,该字体或语言包通常高度依赖于语言。[这是](http://bn.wikipedia.org/wiki/%E0%A6%89%E0%A6%87%E0%A6%95%E0%A6%BF%E0%A6%AA%E0%A7%87%E0%A6%A1%E0%A6%BF%E0%A6%AF%E0%A6%BC%E0%A6%BE:Bangla_script_display_and_input_help)孟加拉语帮助文件[的示例](http://bn.wikipedia.org/wiki/%E0%A6%89%E0%A6%87%E0%A6%95%E0%A6%BF%E0%A6%AA%E0%A7%87%E0%A6%A1%E0%A6%BF%E0%A6%AF%E0%A6%BC%E0%A6%BE:Bangla_script_display_and_input_help)。我肯定那里也有其他人。您只需要将用户指向适当的帮助文件。
#### 偶尔使用
一个很好的例子,当您看到嵌入在非常平淡的ASCII中的一些非常晦涩的Unicode字符时,是[国际语音字母(IPA)的字母](http://en.wikipedia.org/wiki/International_Phonetic_Alphabet),用于以非常标准的方式指定发音(您可能会看到它们在字典中的时间)。您的平均字体可能不支持所有IPA字符,例如ʘ(双音)或ʒ(发声后齿擦音)。那么,浏览器性能不佳怎么办?字体混合!诸如Mozilla Firefox和Internet Explorer 7的智能浏览器将从其他字体中借用字形,以确保所有字符都能正确显示。
但是,如果浏览器不智能并且恰好是全世界使用最广泛的浏览器,会发生什么?当一个字符不存在时,Microsoft IE 6不够聪明,无法从其他字体中借用,因此通常您会被一个漂亮的大字符拍打。为了使一切正常,MSIE 6需要一些微调。您可以将其配置为使用其他字体来呈现文本,但是可以通过有选择地将特殊字符块的字体更改为已知的Unicode字体来达到相同的效果。
幸运的是,维基百科的人们已经为您完成了所有繁重的工作。从此处获取CSS:[Common.css](http://en.wikipedia.org/wiki/MediaWiki:Common.css),并搜索“ .IPA”。还有一些其他类可用于其他目的,请查看[此页面](http://meta.wikimedia.org/wiki/Help:Special_characters#Displaying_Special_Characters)以获取更多详细信息。对于那些懒惰的人,这应该可以工作:
~~~
.Unicode {
字体家族:Code2000,“ TITUS Cyberbit Basic”,“ Doulos SIL”,
“ Chrysanthi Unicode”,“ Bitstream Cyberbit”,
“ Bitstream CyberBase”,Throomanes,Gentium,GentiumAlt,
“ Lucida Grande”,“ Arial Unicode MS”,“ Microsoft Sans Serif”,
“ Lucida Sans Unicode”;
字体家族/ ** /:inherit; / *为IE6以外的所有人重置字体* /
}
~~~
标准用法遵循`<span class="Unicode">Crazy Unicode stuff here</span>`。通常不需要修复[Windows字形列表](http://en.wikipedia.org/wiki/Windows_Glyph_List_4)中的字符,但是对于其他任何事情,您可能都希望安全播放。除非,当然,除非您不关心IE6用户。
### 处理函数中的可变宽度
当人们声称PHP6将解决我们所有的Unicode问题时,他们被误导了。它不会解决任何上述问题。但是,它将解决我们将要讨论的问题:在PHP中处理UTF-8文本。
PHP(从PHP5开始)根本没有意识到UTF-8的存在(有一些值得注意的例外)。有时,这会引起问题,而其他时候则不会。到目前为止,我们避免讨论UTF-8的体系结构,因此,我们首先要问什么是UTF-8?是的,它支持Unicode,是的,它是可变宽度。其他特点:
* 每个字符的字节序列都是唯一的,永远不会在另一个字符的字节序列内找到,
* UTF-8最多可以使用四个字节来编码字符,
* 必须检查UTF-8文本的格式是否正确,
* 纯ASCII也是有效的UTF-8,并且
* 二进制排序将按照与Unicode相同的顺序对UTF-8进行排序。
这些特征中的每一个都以不同的方式影响文本处理的不同领域。解释这些含义的确切含义超出了本文档的范围。PHPWact提供了一个很好的[参考文档](http://www.phpwact.org/php/i18n/utf-8),说明了对每个功能的期望,尽管在某些方面涉及面很广。他们关于[字符集的](http://www.phpwact.org/php/i18n/charsets)更一般的注释也值得一看,以获取有关UTF-8的信息。处理Unicode文本时的一些经验法则:
* 请勿使用以下功能:
* ...转换大小写(strtolower,strtoupper,ucfirst,ucwords)
* ...声称不区分大小写(str\_ireplace,stristr,strcasecmp)
* 使用以下函数之前请三思:
* ...计算字符(strlen将返回字节,而不是字符; str\_split和word\_wrap可能会损坏)
* ...将字符转换为实体引用(UTF-8不需要实体)
* ...执行非常复杂的字符串处理(\* printf)
注意:此列表仅适用于UTF-8编码的文本:如果您拥有100%确定是ASCII的字符串,请成为我的客人并使用`strtolower`(HTML Purifier使用此功能。)
无论如何,请始终以字节为单位,而不是以字符为单位。如果使用strpos()查找字符的位置,它将以字节为单位,但这通常无关紧要,因为substr()也可以使用字节索引操作!
您还需要确保您的UTF-8格式正确,并且可能需要替换其中一些功能。我建议使用Harry Fuecks的[PHP UTF-8](http://phputf8.sourceforge.net/)库,而不是直接使用mb\_string。HTML Purifier还定义了一些有用的UTF-8兼容功能:`Encoder.php`在`/library/HTMLPurifier/`目录中检出。
## 进一步阅读
好吧,就是这样。希望该文档对了解UTF-8的工作原理起到了非常实用的跳板作用。您可能已经决定不迁移:很好,只知道输出将发生什么以及可能收到的错误报告。
许多其他开发人员已经讨论了Unicode,UTF-8和国际化的主题,我想请他们对字符集和编码进行更深入的研究。
* [绝对最低每一个软件开发人员绝对,积极必须知道的关于Unicode和字符集(没有借口!)](http://www.joelonsoftware.com/articles/Unicode.html)由Joel Spolsky的,提供了一个*非常*以Unicode和字符集在总体上是好的高水平的样子。
* [Wikipedia上](http://en.wikipedia.org/wiki/UTF-8)的UTF-8为UTF-8的内幕提供了许多有用的细节,尽管对于一开始不太了解Unicode的人来说可能有些反感。
- php更新内容
- PHP PSR 标准规范
- 辅助查询(*)
- composer项目的创建
- composer安装及设置
- composer自动加载讲解
- phpsdudy的composer操作
- git
- Git代码同时上传到GitHub和Gitee(码云)
- Git - 多人协同开发利器,团队协作流程规范与注意事项
- 删除远程仓库的文件
- github查询方法
- 错误
- 其他
- php.ini
- php配置可修改范围
- php超时
- 防跨目录设置
- 函数可变参数
- 【时间】操作
- 时间函数例子
- Date/Time 函数(不包含别名函数)
- DateTime类别名函数
- 【数字】操作
- 【字符串】操作
- 【数组】操作
- 排序
- 合并案例
- empty、isset、is_null
- echo 输出bool值
- if真假情况
- 流程控制代替语法【if (条件): endif;】
- 三元运算
- 运算符优先级
- 常量
- define与const(php5.3) 类常量
- 递归
- 单元测试
- 面向对象
- 对象(object) 与 数组(array) 的转换
- php网络相关
- 支持的协议和封装协议(如http,php://input)
- php://协议
- file://协议
- http(s)://协议
- ftp(s)://协议
- zip://, bzip2://, zlib://协议
- data://协议
- glob://协议
- expect://协议
- phar://
- ssh2
- rar://
- ogg://
- 上下文(Context)选项和参数
- 过滤器
- http请求及模拟登录
- 常用的header头部定义汇总
- HTTP响应头和请求头信息对照表
- HTTP请求的返回值含义说明
- content-type对照表
- Cache-Control对照
- curl函数
- 防止页面刷新
- telnet模拟get、post请求
- 三种方式模拟表单发布留言
- 模拟登陆
- 防盗链
- php+mysql模拟队列发送邮件
- socket
- 使用websocket实现php消息实时推送完整示例
- streams
- Stream函数实现websocket
- swoole
- 网络编程基本概念
- 全局变量域超全局变量
- 超全局变量
- $_ENV :存储了一些系统的环境变量
- $_COOKIE
- $_SESSION
- $_FILES
- $_SERVER
- 正则
- php正则函数
- 去除文本中的html、xml的标签
- 特殊符号
- \r\n
- 模式修正符
- 分组
- 断言(环视?)
- 条件表达式
- 递归表达式 (?R)
- 固化分组
- 正则例子
- 提取类文件的公共方法
- 抓取网页内容
- 匹配中文字符
- 提取sql日志文件
- 框架
- 文件操作
- 自动加载spl_autoload_register
- 文件加载
- 文件的上传下载
- 常见的mimi类型
- 文件断点续传
- 下载文件防盗链
- 破解防盗链
- 将字节转为人可读的单位
- 无限分类
- 短信验证码
- 短信宝
- 视频分段加载
- 隐藏地址
- MPEG DASH视频分片技术
- phpDoc注释
- @错误抑制符
- 字符编码
- PHP CLI模式开发
- CGI、FastCGI和PHP-FPM关系图解
- No input file specified的解决方法
- SAPI(PHP常见的四种运行模式)
- assert断言
- 轮询(Event Loop)
- 异常处理
- 异常分类
- php系统异常
- 错误级别
- set_error_handler
- set_exception_handler
- register_shutdown_function
- try catch
- tp5异常处理类解析
- 文件上传相关设置
- 进程/线程/协程
- 协程
- 什么是协程
- 引用&
- Heredoc和Nowdoc语法
- 类基础
- 系统预定义类
- pdo
- 类的三大特性:封装,继承,多态
- 魔术方法
- extends继承
- abstract 抽象类
- interface 接口(需要implements实现)
- 抽象类和接口的区别
- 多态
- static
- final
- serialize与unserialize
- instanceof 判断后代子类
- 类型约束
- clone克隆
- ::的用法
- static::class、self::class
- new self()与new static()
- this、self、static、parent、super
- self、static、parent:后期静态绑定
- PHP的静态变量
- php导入
- trait
- 动态调用类方法
- 参数及类型申明
- 方法的重载覆盖
- return $a && $b
- 类型声明
- 设计思想
- 依赖注入与依赖倒置
- MVC模式与模板引擎
- 模版引擎
- smarty模版
- 系统变量、全局变量
- 语言切换
- 函数-给函数默认值
- 流程控制-遍历
- 模版加载
- 模版继承
- blade
- twig
- Plates
- 创建型模式(创建类对象)--单原二厂建
- (*)单例模式(保证一个类仅有一个实例)
- (*)工厂模式(自动实例化想要的类)
- 原型模式(在指定方法里克隆this)
- 创建者模式(建造者类组装近似类属性)
- 结构型模式 --桥(帮)组享外带装适
- 适配器模式(Adapter 用于接口兼容)
- 桥接模式(方法相同的不同类之间的快速切换)
- 装饰模式(动态增加类对象的功能 如游戏角色的装备)
- 组合模式(用于生成类似DOMDocument这种节点类)
- 外观模式(门面(Facade)模式 不同类的统一调用)
- 享元模式
- 代理模式
- 行为型模式--观摩职命状-备爹在房中洁厕
- (*)观察者模式
- (*)迭代器模式(Iterator)
- 模板方法模式 Template
- 命令模式(Command)
- 中介者模式(Mediator)
- 状态模式(State)
- 职责链模式 (Chainof Responsibility)
- 策略模式(Strategy)
- 已知模式-备忘录模式(Memento)
- 深度模式-解释器模式(Interpreter)
- 深度模式-访问者模式(Visitor)
- (*)注册树(注射器、注册表)模式
- PHP扩展库列表
- 函数参考
- 影响 PHP 行为的扩展
- APC扩展(过时)
- APCu扩展
- APD扩展(过时)
- bcompiler扩展(过时)
- BLENC扩展 (代码加密 实验型)
- Componere扩展(7.1+)
- Componere\Definition
- Componere\Patch
- Componere \ Method
- Componere\Value
- Componere函数
- 错误处理扩展(PHP 核心)
- FFI扩展
- 基本FFI用法
- FFI api
- htscanner扩展
- inclued扩展
- Memtrack扩展
- OPcache扩展(5.5.0内部集成)
- Output Control扩展(核心)
- PHP Options/Info扩展(核心)
- 选项、 信息函数
- phpdbg扩展(5.6+内部集成)
- runkit扩展
- runkit7扩展
- scream扩展
- uopz扩展
- Weakref扩展
- WeakRef
- WeakMap
- WinCache扩展
- Xhprof扩展
- Yac(7.0+)
- 音频格式操作
- ID3
- KTaglib
- oggvorbis
- OpenAL
- 身份认证服务
- KADM5
- Radius
- 针对命令行的扩展
- Ncurses(暂无人维护)
- Newt(暂无人维护)
- Readline
- 压缩与归档扩展
- Bzip2
- LZF
- Phar
- Rar
- Zip
- Zlib
- 信用卡处理
- 加密扩展
- Crack(停止维护)
- CSPRNG(核心)
- Hash扩展(4.2内置默认开启、7.4核心)
- Mcrypt(7.2移除)
- Mhash(过时)
- OpenSSL(*)
- 密码散列算法(核心)
- Sodium(+)
- 数据库扩展
- 数据库抽象层
- DBA
- dbx
- ODBC
- PDO(*)
- 针对各数据库系统对应的扩展
- CUBRID
- DB++(实验性)
- dBase
- filePro
- Firebird/InterBase
- FrontBase
- IBM DB2
- Informix
- Ingres
- MaxDB
- Mongo(MongoDB老版本)
- MongoDB
- mSQL
- Mssql
- MySQL
- OCI8(Oracle OCI8)
- Paradox
- PostgreSQL
- SQLite
- SQLite3
- SQLSRV(SQL Server)
- Sybase
- tokyo_tyrant
- 日期与时间相关扩展
- Calendar
- 日期/时间(核心)
- HRTime(*)
- 文件系统相关扩展
- Direct IO
- 目录(核心)
- Fileinfo(内置)
- 文件系统(核心)
- Inotify
- Mimetype(过时)
- Phdfs
- Proctitle
- xattr
- xdiff
- 国际化与字符编码支持
- Enchant
- FriBiDi
- Gender
- Gettext
- iconv(内置默认开启)
- intl
- 多字节字符串(mbstring)
- Pspell
- Recode(将要过时)
- 图像生成和处理
- Cairo
- Exif
- GD(内置)
- Gmagick
- ImageMagick
- 邮件相关扩展
- Cyrus
- IMAP
- Mail(核心)
- Mailparse
- vpopmail(实验性 )
- 数学扩展
- BC Math
- GMP
- Lapack
- Math(核心)
- Statistics
- Trader
- 非文本内容的 MIME 输出
- FDF
- GnuPG
- haru(实验性)
- Ming(实验性)
- wkhtmltox(*)
- PS
- RPM Reader(停止维护)
- RpmInfo
- XLSWriter Excel操作(*)
- php第三方库非扩展
- 进程控制扩展
- Eio
- Ev
- Expect
- Libevent
- PCNTL
- POSIX
- 程序执行扩展(核心)
- parallel
- pthreads(*)
- pht
- Semaphore
- Shared Memory
- Sync
- 其它基本扩展
- FANN
- GeoIP(*)
- JSON(内置)
- Judy
- Lua
- LuaSandbox
- Misc(核心)
- Parsekit
- SeasLog(-)
- SPL(核心)
- SPL Types(实验性)
- Streams(核心)
- stream_wrapper_register
- stream_register_wrapper(同上别名)
- stream_context_create
- stream_socket_client
- stream_socket_server
- stream_socket_accept
- stream_socket_recvfrom
- stream_socket_sendto
- Swoole(*)
- Tidy扩展
- Tokenizer
- URLs(核心)
- V8js(*)
- Yaml
- Yaf
- Yaconf(核心)
- Taint(检测xss字符串等)
- Data Structures
- Igbinary(7.0+)
- 其它服务
- 网络(核心)
- Sockets
- socket_create
- socket_bind(服务端即用于监听的套接字)
- socket_listen(服务端)
- socket_accept(服务端)
- socket_connect(客户端)
- socket_read
- socket_recv(类似socket_read)
- socket_write
- socket_send
- socket_close
- socket_select
- socket_getpeername
- socket_getsockname
- socket_get_option
- socket_getopt(socket_get_option的别名)
- socket_set_option
- socket_setopt( socket_set_option的别名)
- socket_recvfrom
- socket_sendto
- socket_addrinfo_bind
- socket_addrinfo_connect
- socket_addrinfo_explain
- socket_addrinfo_lookup
- socket_clear_error
- socket_last_error
- socket_strerror
- socket_cmsg_space
- socket_create_listen
- socket_create_pair
- socket_export_stream
- socket_import_stream
- socket_recvmsg
- socket_sendmsg
- socket_set_block
- socket_set_nonblock
- socket_shutdown
- socket_wsaprotocol_info_export
- socket_wsaprotocol_info_import
- socket_wsaprotocol_info_release
- cURL(*)
- curl_setopt
- Event(*)
- chdb
- FAM
- FTP
- Gearman
- Gopher
- Gupnp
- Hyperwave API(过时)
- LDAP(+)
- Memcache
- Memcached(+)
- mqseries
- RRD
- SAM
- ScoutAPM
- SNMP
- SSH2
- Stomp
- SVM
- SVN(试验性的)
- TCP扩展
- Varnish
- YAZ
- YP/NIS
- 0MQ(ZeroMQ、ZMQ)消息系统
- 0mq例子
- ZooKeeper
- 搜索引擎扩展
- mnoGoSearch
- Solr
- Sphinx
- Swish(实验性)
- 针对服务器的扩展
- Apache
- FastCGI 进程管理器
- IIS
- NSAPI
- Session 扩展
- Msession
- Sessions
- Session PgSQL
- 文本处理
- BBCode
- CommonMark(markdown解析)
- cmark函数
- cmark类
- Parser
- CQL
- IVisitor接口
- Node基类与接口
- Document
- Heading(#)
- Paragraph
- BlockQuote
- BulletList
- OrderedList
- Item
- Text
- Strong
- Emphasis
- ThematicBreak
- SoftBreak
- LineBreak
- Code
- CodeBlock
- HTMLBlock
- HTMLInline
- Image
- Link
- CustomBlock
- CustomInline
- Parle
- 类函数
- PCRE( 核心)
- POSIX Regex
- ssdeep
- 字符串(核心)
- 变量与类型相关扩展
- 数组(核心)
- 类/对象(核心)
- Classkit(未维护)
- Ctype
- Filter扩展
- 过滤器函数
- 函数处理(核心)
- quickhash扩展
- 反射扩展(核心)
- Variable handling(核心)
- Web 服务
- OAuth
- api
- 例子:
- SCA(实验性)
- SOAP
- Yar
- XML-RPC(实验性)
- Windows 专用扩展
- COM
- 额外补充:Wscript
- win32service
- win32ps(停止更新且被移除)
- XML 操作(也可以是html)
- libxml(内置 默认开启)
- DOM(内置,默认开启)
- xml介绍
- 扩展类与函数
- DOMNode
- DOMDocument(最重要)
- DOMAttr
- DOMCharacterData
- DOMText(文本节点)
- DOMCdataSection
- DOMComment(节点注释)
- DOMDocumentFragment
- DOMDocumentType
- DOMElement
- DOMEntity
- DOMEntityReference
- DOMNotation
- DOMProcessingInstruction
- DOMXPath
- DOMException
- DOMImplementation
- DOMNamedNodeMap
- DOMNodeList
- SimpleXML(内置,5.12+默认开启)
- XMLReader(5.1+内置默认开启 用于处理大型XML文档)
- XMLWriter(5.1+内置默认开启 处理大型XML文档)
- SDO(停止维护)
- SDO-DAS-Relational(试验性的)
- SDO DAS XML
- WDDX
- XMLDiff
- XML 解析器(Expat 解析器 默认开启)
- XSL(内置)
- 图形用户界面(GUI) 扩展
- UI
- PHP SPL(PHP 标准库)
- 数据结构
- SplDoublyLinkedList(双向链表)
- SplStack(栈 先进后出)
- SplQueue(队列)
- SplHeap(堆)
- SplMaxHeap(最大堆)
- SplMinHeap(最小堆)
- SplPriorityQueue(堆之优先队列)
- SplFixedArray(阵列【数组】)
- SplObjectStorage(映射【对象存储】)
- 迭代器
- ArrayIterator
- RecursiveArrayIterator(支持递归)
- DirectoryIterator类
- FilesystemIterator
- GlobIterator
- RecursiveDirectoryIterator
- EmptyIterator
- IteratorIterator
- AppendIterator
- CachingIterator
- RecursiveCachingIterator
- FilterIterator(遍历并过滤出不想要的值)
- CallbackFilterIterator
- RecursiveCallbackFilterIterator
- RecursiveFilterIterator
- ParentIterator
- RegexIterator
- RecursiveRegexIterator
- InfiniteIterator
- LimitIterator
- NoRewindIterator
- MultipleIterator
- RecursiveIteratorIterator
- RecursiveTreeIterator
- 文件处理
- SplFileInfo
- SplFileObject
- SplTempFileObject
- 接口 interface
- Countable
- OuterIterator
- RecursiveIterator
- SeekableIterator
- 异常
- 各种类及接口
- SplSubject
- SplObserver
- ArrayObject(将数组作为对象操作)
- SPL 函数
- 预定义接口
- Traversable(遍历)接口
- Iterator(迭代器)接口
- IteratorAggregate(聚合式迭代器)接口
- ArrayAccess(数组式访问)接口
- Serializable 序列化接口
- JsonSerializable
- Closure 匿名函数(闭包)类
- Generator生成器类
- 生成器(php5.5+)
- yield
- 反射
- 一、反射(reflection)类
- 二、Reflector 接口
- ReflectionClass 类报告了一个类的有关信息。
- ReflectionObject 类报告了一个对象(object)的相关信息。
- ReflectionFunctionAbstract
- ReflectionMethod 类报告了一个方法的有关信息
- ReflectionFunction 类报告了一个函数的有关信息。
- ReflectionParameter 获取函数或方法参数的相关信息
- ReflectionProperty 类报告了类的属性的相关信息。
- ReflectionClassConstant类报告有关类常量的信息。
- ReflectionZendExtension 类返回Zend扩展相关信息
- ReflectionExtension 报告了一个扩展(extension)的有关信息。
- 三、ReflectionGenerator类用于获取生成器的信息
- 四、ReflectionType 类用于获取函数、类方法的参数或者返回值的类型。
- 五、反射的应用场景
- phpRedis
- API
- API详细
- redis DB 概念:
- 通用命令:rawCommand
- Connection
- Server
- List
- Set
- Zset
- Hash
- string
- Keys
- 事物
- 发布订阅
- 流streams
- Geocoding 地理位置
- lua脚本
- Introspection 自我检测
- biMap
- 原生
- php-redis 操作类 封装
- redis 队列解决秒杀解决超卖:
- swoole+框架笔记
- 安装及常用Cli操作
- TCP
- 4种回调函数的写法
- easyswoole
- 目录结构
- 配置文件
- Linux+Nginx
- 前置
- linux
- 开源网站镜像及修改yum源
- 下载linux
- Liunx中安装PHP7.4 的三种方法(Centos8)
- yum安装
- 源码编译安装
- LNMP一键安装
- 查看linux版本号
- 设置全局环境变量
- 查看php.ini必须存放的位置
- 防火墙与端口开放
- nohup 后台运行命令
- linux 查看nginx,php-fpm运行用户及用户组
- 网络配置
- CentOS中执行yum update时报错
- 关闭防火墙
- 查看端口是否被占用
- 查看文件夹大小
- nginx相关
- 一个典型的nginx配置
- nginx关于多个项目的配置(易于管理)
- nginx.config配置文件的结构
- 1、events
- 2、http
- nginx的location配置详解
- Nginx相关命令
- Nginx安装
- 配置伪静态
- 为静态配置例子
- apache
- nginx
- pathinfo模式
- Shell脚本
- bash
- shell 语言中 0 代表 true,0 以外的值代表 false。
- 变量
- shell字符串
- shell数组
- shell注释
- 向Shell脚内传递参数
- 运算符
- 显示命令执行结果
- printf
- test 命令
- 流程控制与循环
- if
- case
- for
- while
- until
- break和continue
- select 结构
- shell函数
- shell函数的全局变量和局部变量
- 将shell输出写入文件中(输出重定向)
- Shell脚本中调用另一个Shell脚本的三种方式
- 定时任务
- PHP实现定时任务的五种方法
- 优化
- ab压力测试
- 缓存
- opcache
- memcache
- php操作
- 数据库
- 配置
- 数据库锁机制
- 主从分布
- 数据库设计
- 逻辑设计
- 物理设计
- 字段类型的选择
- 笔记
- SET FOREIGN_KEY_CHECKS
- 字符集与乱码
- SQL插入 去除重复记录的实现
- 分区表
- nginx 主从配置
- nginx 负载均衡的配置
- 手动搭建Redis集群和MySQL主从同步(非Docker)
- Redis Cluster集群
- mysql主从同步
- 用安卓手机搭建 web 服务器
- 软件选择
- url重写
- 大流量高并发解决方案
- 权限设计
- ACL
- RBAC
- RBAC0
- RBAC1(角色上下级分层)
- RBAC2(用户角色限约束)
- RBAC3
- 例子
- Rbac.class.php
- Rbac2
- Auth.class.php
- fastadmin Auth
- tree1
- ABAC 基于属性的访问控制
- 总结:SAAS后台权限设计案例分析
- casbin-权限管理框架
- 开始使用
- casbinAPI
- casbin管理API
- RBAC API
- Think-Casbin
- 单点登录(SSO)
- OAuth授权
- OAuth 2.0 的四种方式
- 授权码
- 隐藏式
- 密码式
- 凭证式
- 更新令牌
- 例子:第三方登录
- 微服务架构下的统一身份认证和授权
- 代码审计
- 漏洞挖掘的思路
- 命令注入
- 代码注入
- XSS 反射型漏洞
- XSS 存储型漏洞
- xss过滤
- HTML Purifier文档
- 开始
- id规则
- class规则
- 过滤分类
- Attr
- AutoFormat
- CSS
- Cache
- Core
- Filter
- html
- Output
- Test
- URI
- 其他
- 嵌入YouTube视频
- 加快HTML净化器的速度
- 字符集
- 定制
- Tidy
- URI过滤器
- 在线测试
- xss例子
- 本地包含与远程包含
- sql注入
- 函数
- 注释
- 步骤
- information_schema
- sql注入的分类
- 实战
- 防御
- CSRF 跨站请求伪造
- 计动态函数执行与匿名函数执行
- unserialize反序列化漏洞
- 覆盖变量漏洞
- 文件管理漏洞
- 文件上传漏洞
- 跳过登录
- URL编码对照表
- XXE
- 前端、移动端
- html5
- meta标签
- flex布局
- javascript
- jquery
- 选择器
- 精细分类
- 事件
- on事件无效:
- jquery自定义事件
- 表单操作
- 通用
- select
- checkbox
- radio
- js正则相关
- js中判断某字符串含有某字符出现的次数
- js匹配指定字符
- $.getjson方法配合在url上传递callback=?参数,实现跨域
- pajax入门
- jquery的extend插件制作
- jquery的兼容
- jquery的连续调用:
- $ 和 jQuery 及 $() 的区别
- 页面响应顺序及$(function(){})等使用
- 匿名函数:
- ajax
- 获取js对象所有方法
- dom加载
- ES6函数写法
- ES6中如何导入和导出模块
- 数组的 交集 差集 补集 并集
- phantomjs
- js数组的map()方法操作json数组
- 实用函数
- js精确计算CalcEval 【价格计算】 浮点计算
- js精确计算2
- js数组与对象的遍历
- bootstrap
- class速查
- 常见data属性
- data-toggle与data-target的作用
- 组件
- bootstrapTable
- 表选项
- 表选项2
- 示例
- 数据格式(json)
- 用法(row:行,column:列)
- Bootstrap-table使用footerFormatter做统计列功能
- 示例2
- JQuery-Jquery的TreeGrid插件
- 服务器端分页
- 合并单元格1
- 合并单元格2
- 合并单元格3
- 合并单元格4
- 合并单元格5(插件)
- 列求和
- 添加行,修改行、扩展行数据
- 扩展
- 开源项目
- PhpSpreadsheet
- 实例
- 会员 数据库表设计
- 程序执行
- 开发总结
- API接口
- API接口设计
- json转化
- app接口
- 杂项
- 三方插件库
- 检测移动设备(包括平板电脑)
- curl封装
- Websocket
- 与谷歌浏览器交互
- Crontab管理器
- 实用小函数
- PHP操作Excel
- SSL证书
- sublime Emmet的快捷语法
- 免费翻译接口
- 接口封装
- 免费空间
- 架构师必须知道的26项PHP安全实践
- 大佬博客
- 个人支付平台
- RPC(远程调用)及框架