本文最后更新于:2024年3月18日 凌晨
PHP 编码与转义
- 因为PHP程序经常与HTML页,Web地址(URL)以及数据库交互,所以PHP提供一些函数来帮助你处理这些类型的数据,HTML,Web页地址和数据库命令都是字符串,但是它们每个都要求不同的字符以不同的方法来转义,例如,在Web地址中一个空格被写作%20,而直接量小于符号(<)在HTML文档中必须写作<,PHP有许多内置函数来转换和取得这些编码。
HTML
- 在HTML中特殊的字符以实体(entify)表示,如
&
和<
,这里有两个PHP函数来吧字符串中的特殊字符转换为实体,一个用于删除HTML标签,一个仅用于提取meta标签。
对所有特殊字符进行实体引用
- 函数
htmlentities()
将HTML字符转换为对应的实体(除了空格符),包括小于符号<
,大于符号>
,与符号&
和重音字符。
- 例如:
1 2 3 4
| $string = htmlentities("a < b"); echo $string;
a < b
|
- 经过实体转义的版本在Web页面中正确地显示了
<
(如果在页面上点右键,查看源代码可以看到实体<
),如你所看到的那样,空格没有被转换成$nbsp;
- 函数
htmlentities()
实际上有3个参数:
1
| $output = htmlentities(input,quote_style,charset);
|
- 如果给了参数,charset则识别字符集,默认的字符集时"ISO-8859-1",参数
quote_style
控制单引号和双引号是否变成它们实体的形式,ENT_COMPAT
(默认值)只转换双引号,ENT_QUOTES
两种引号都转换,ENT_NOQUOTES
则一种都不转换,没有只转换单引号的选项,例如:
1 2 3 4 5 6
| $input = <<<End; "Stop pulling my hair!" Jane's eyes flashed.<p> End; $double = htmlentities($input); // 输出:"Stop pulling my hair!" Jane's eyes flashed.<p> $both = htmlentities($input,ENT_QUOTES); $neither = htmlentities($input,ENT_NOQUOTES);
|
只对HTML语法字符进行实体引用
- 函数
htmlspecialchars()
转换最小的实体集来生成合法的HTML,下面的实体被转换:
- 与符号
&
被转换成&
- 双引号
"
被转换成"
- 单引号
'
被转换成'
(就像调用htmlentities()
时使用ENT_QUOTES
的效果)
- 小于号
<
被转换成<
- 大于号
>
被转换成>
- 如果有一个应用程序来显示用户填入表单的数据,则要在显示和保存数据之前通过
htmlspecialchars()
处理数据,如果没有处理的话,一旦用户提交了像angle < 30
或sturm & drang
这样的字符串,浏览器会认为这些特殊的字符时HTML,从而得到一个混乱的页面。
- 和
htmlentities()
类似,htmlspecialchars()
可以有3个参数:
1
| $output = htmlspecialchars(input,[quote_style,[charset]])
|
- 参数
quote_style
和charset
同它们在htmlentities()
中的意义相同。
- 没有专门的函数来把实体转换回原始的文本,因为很少需要这样做,不过这里有一个相对简单的方法来完成这个任务,使用函数
get_html_translation_table()
用特定引号的方式获取被任一转换函数使用的转换表,例如,要获得htmlentities()
使用的转换表,可以这样做:
1
| $table = get_html_translation_table(HTML_ENTITIES);
|
- 要在
ENT_NOQUOTES
模式下获得htmlspecialchars()
的转换表,可以这样做:
1
| $table = get_html_translation_table(HTML_SPECIALCHARS,ENT_NOQUOTES);
|
- 使用转换表的一个小技巧是,用
array_flip()
翻转它,并把它传给strtr()
来得到一个字符串,因此有效的回滚htmlentities()
操作的方法是:
1 2 3 4 5 6
| $str = htmlentities("a < b"); $table = get_html_translation_table(HTML_ENTITIES); $rev_trans = array_flip($table); echo strtr($str,$rev_trans);
a < b
|
- 当然,你也可以取出转换表,增加你想要它转化的其他东西,然后使用
strtr()
,例如,如果想让htmlentities()
把空格编码为
,可以这样做:
1 2 3
| $table = get_html_translation_table(HTML_ENTITIES); $table[' '] = ' '; $encoded = strtr($original,$table);
|
删除HTML标签
- 函数
strip_tags()
从字符串中删除HTML标签:
1 2
| $input = '<p>Howdy, "Cowboy"</p>'; $output = strip_tags($input);
|
- 函数可以有第二个参数来指定在字符串中留下的标签,只列出标签的开始形式,在第二个参数中列出的标签结束形式也将被保留:
1 2
| $input = 'The <b>bold</b> tags will <i>stay</i><p>'; $output = strip_tags($input,'<b>');
|
- 在保留标签中的属性不会被
strip_tags()
改变,由于HTML标签属性(例如style和onmouseover)可以影响Web页面的外观和行为,所以用strip_tags()
保留一些标签可能会导致无法删除所有潜在的冗余内容。
提取元标签
- 如果你把Web页面的HTML存在一个字符串中,函数
get_meta_tags()
可返回包含该页面中元标签(meta tag)内容的数组,元标签的名字(keywords,author,escription等)成为数组的键,而元标签的内容则成为对应的值:
1 2 3 4
| $meta_tags = get_meta_tags('http://www.example.com/'); echo "Web page made by {$meta_tags[author]}";
Web page made by John Doe
|
1
| $array = get_meta_tags(filename[,use_include_path]);
|
- 可以指定参数
use_include_path
为true,这样可使PHP尝试用标准包含路径打开文件。
URLs URL
- PHP提供了一些函数用于对URL进行编码和解码,实际上有两种方法对URL编码,其区别在于如何处理空格,第一种(根据RFC1738规范)把空格当作URL中的另一个非法字符并把它编码为
%20
,第二种(执行application/x-www-form-urlencoded
系统)把空格编码为一个+
并且把它用于建立查询的字符串中。
- 注意并不需要对一个完整的URL使用这些函数,例如http://www.example.com/hello,因为它们会转义冒号和反斜杠:
1
| http%3A%2F%2Fwww.example.com%2Fhello
|
RFC1738编码和解码
- 要把字符串依照URL约定编码,可以使用
rawurlencode()
;
1
| $output = rawurlencode(input);
|
- 该函数接受一个字符串并返回对该字符串的拷贝,该拷贝中把非法URL字符按%dd约定编码。
- 如果你要为一个页面里的链接动态生成超级链接地址,则需要用
rawurlencode()
转换它们:
1 2 3 4 5
| $name = "programming PHP"; $output = rawurlencode($name); echo "http://localhost/$output";
http:
|
- 查询字符串编码。
urlencode()
和urlencode()
函数和它们原始版本(即rawurlencode()
和rawurldecode()
)的不同仅在于它们把空格编码为加号+
,而不是%20
,这是用于创建查询字符串(query string)和cookie值得格式,但是因为这些值在通过表单或cookie传送时会自动解码,所以你不需要使用这些函数来处理当前页的查询字符串或cookie,这两个函数对于生成查询字符串是很有用的:
1 2 3 4 5 6
| $base_url = 'http://google.com/q='; $query = 'PHP sessions -cookies'; $url = $base_url.urlencode($query); echo $url;
http:
|
SQL
- 绝大多数数据库系统都要求将SQL查询字符串进行转义,SQL的转义方法相当简单–在单引号,双引号,空字节和反斜杠前面加上一个反斜杠(\),
addslashes()
函数可添加这些反斜杠,stripslashes()
函数则删除它们:
1 2 3 4 5 6 7 8 9 10 11 12 13
| $string = <<< The_End "It's never going to work,"she cried, as she hit the backslash(\)key. The_End; echo addslashes($string);
\"It\'s never going to work,\"she cried, as she hit the backslash(\\)key.
echo stripslashes($string);
"It's never going to work,"she cried, as she hit the backslash(\)key.
|
提示:一些数据库(如SYBASE)用另一个单引号为单引号转义,而不是一个反斜杠,对于这些数据库,可以在php.ini文件中打开magic_quores_sybase
C语言字符串编码
addcslashes()
函数模仿C编程语言的处理方式,通过在字符前加反斜杠来转义任意字符,除了下表中的字符,ASCII值小于32或大于126的字符将使用它们的八进制值(例如,“\002”)进行编码,addcslashes()
和stripcslapshes()
函数常常被用于非标准的数据库系统,这些系统对哪些字符需要被转义有自己的要求。
ASK值 |
编码 |
7 |
\a |
8 |
\b |
9 |
\t |
10 |
\n |
11 |
\t |
12 |
\f |
13 |
\r |
- 调用
addcslashes()
时有两个参数–string是要编码的字符串,charset是要转义的字符:
1
| $escaped = addcslashes(string,charset);
|
1 2 3
| echo addcslashes("hello\tworld\n","\x00..\x2fz..\xff");
hello\\tworld\\n
|
- 如果将
0
,a
,b
,f
,n
,r
,t
或v
指定在要转换的字符范围中,要特别注意它们会被转换成\0
,\a
等,C和PHP可以识别这些转义序列(如\0在PHP中时预定义序列,表示NULL),可能会引起混乱。
stripcslashes()
接受一个字符串并返回去掉转义后的新字符串。
1
| $string = stripcslapshes(escaped);
|
1
| $string = stripcslapshes('hello\tworld\n');
|