
问题描述
在web开发中,我们经常需要通过url传递参数。php通过$_get超全局变量来获取这些参数。然而,当url参数的值本身包含特殊字符&时,php的默认行为会导致问题。
考虑以下URL: page.php?clss_type=Boys%20&%20Girls
如果尝试使用$_GET['clss_type']来获取clss_type的值,例如:
期望的输出是Boys & Girls,但实际的输出会是Boys。这是因为PHP默认将&符号识别为URL查询字符串中不同参数的分隔符。当PHP解析到clss_type=Boys%20&%20Girls时,它会将第一个&视为clss_type参数的结束,并尝试将%20Girls解析为另一个参数(或忽略它,如果它不是一个有效的键值对)。
解决方案一:URL编码(推荐)
最标准和推荐的解决方案是对URL参数值中的特殊字符进行URL编码。&字符在URL编码中应被转义为%26。
1. 正确构造URL
在生成URL时,应确保参数值中的&被正确编码。 将page.php?clss_type=Boys%20&%20Girls修改为: page.php?clss_type=Boys%20%26%20Girls
这里,Boys & Girls被编码为Boys%20%26%20Girls。%20代表空格,%26代表&。
立即学习“PHP免费学习笔记(深入)”;
2. PHP中的处理
当URL被正确编码后,PHP的$_GET变量会自动对其进行解码,开发者无需额外操作。
3. 使用urlencode()函数
在PHP中动态构造URL时,可以使用urlencode()函数来确保参数值被正确编码。
urlencode()函数会将所有非字母数字字符(除了-._)编码为%xx的形式,这包括&、空格、=等,从而确保它们不会被误解析为URL结构的一部分。
解决方案二:修改php.ini配置
另一种方法是改变PHP默认的参数分隔符,但这通常不推荐,因为它是一个全局配置,可能会影响服务器上所有PHP应用程序的行为,且不符合URL参数的通用约定。
1. 修改arg_separator.input指令
在php.ini文件中,arg_separator.input指令定义了PHP用于解析GET参数的字符。默认值为&。 你可以将其修改为其他字符,例如分号;:
; php.ini arg_separator.input = ";"
修改后,需要重启Web服务器(如Apache、Nginx)或PHP-FPM服务使配置生效。
2. URL构造的变化
如果将arg_separator.input设置为;,那么你的URL构造方式也需要改变: page.php?clss_type=Boys%20&%20Girls;another_param=value 在这种情况下,clss_type的值中的&将不会被视为分隔符。
3. 注意事项
- 全局影响: 这个修改会影响服务器上所有PHP应用程序,如果其他应用程序依赖于&作为分隔符,可能会导致问题。
- 非标准: 大多数Web服务和客户端都期望&作为URL参数分隔符。使用其他字符可能会导致兼容性问题。
- 不推荐: 除非有非常特殊的理由,否则不建议使用此方法。URL编码是更通用、更健壮的解决方案。
总结与最佳实践
当URL参数值中包含&等特殊字符时,PHP的默认解析行为会导致数据丢失。为了正确获取这些参数,最推荐和标准的方法是对参数值进行URL编码,将&转义为%26。在PHP中,可以使用urlencode()函数来动态完成这一操作。接收端$_GET会自动解码,无需额外处理。
修改php.ini中的arg_separator.input虽然也能解决问题,但因其全局性、非标准性以及可能带来的兼容性问题,通常不建议采用。始终优先使用URL编码来处理URL参数中的特殊字符,以确保应用程序的健壮性和兼容性。











