The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead
当我尝试从PHP连接到MySQL服务器时,我看到以下错误:
Deprecated: The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /path/to/filename.php on line 123
参考行上的代码是:
1
| mysql_connect($server, $username, $password); |
我确信这些论点是正确的,而且这个精确的代码已经工作了很多年,没有问题。实际上,我是从一个源代码良好的PHP教程中获得的。
为什么会这样?
我怎么修?
我理解,通过在php.ini中设置error_reporting来排除E_DEPRECATED可以抑制折旧错误:
1
| error_reporting = E_ALL ^ E_DEPRECATED |
如果我这样做会发生什么?
- 这里有一个将mysql转换为mysqli的源代码扫描工具:转换为mysqli(2011年12月;作者:Keith Larson;Oracle mysql wiki)
- 使用pdo_query()。这是mysql_uuu中最简单的升级路径,并且使用pdo;这是两个备选方案中比较友好的一个。mysqli实际上只是一个stop-gap api;一开始听起来很吸引新用户,因为名称相似,但是由于函数签名的转换,需要更多的重写,然后甚至使参数化查询更加费力。
- 至于回答问题的题目,PDO更一般,一般来说是一个更好的解决方案。@Dennisdegryse=>虽然我更喜欢面向对象的PDO,但mysqli也有一种面向对象的方式来使用它(搜索"mysqli类")。有关pdo mysqli on code.tutsplus.com/tutorials/…和php.net/manual/en/mysqli.overview.php之间比较的更多信息
- 在Oracle MySQLwiki上找不到任何内容(上面的Weblink评论)。
- @感谢您提供工具链接。正如一般评论一样,请注意,对于某些命令,您不能简单地将mysql_u转换为mysqli_u,因为它们的功能不同。
Why is this happening?
Ok.
整个ext/mysqlphp扩展名在php v5.5.0中被正式否决,并在php v7中被删除,它提供了前缀为mysql_的所有函数。好的。
它最初是在用于MySQLv3.20的php v2.0(1997年11月)中引入的,自2006年以来没有添加任何新功能。再加上缺乏新特性,在复杂的安全漏洞中维护这样的旧代码很困难。好的。
自2011年6月以来,该手册已包含了禁止在新代码中使用的警告。好的。
How can I fix it?
Ok.
如错误消息所示,您可以考虑使用另外两个MySQL扩展:mysqli和pdo-mysql,其中任何一个都可以代替ext/mysql。这两个版本都是从v5.0开始就在php核心中的,所以如果您使用的是一个会抛出这些反预测错误的版本,那么您几乎可以肯定地立即开始使用它们,也就是说,不需要任何安装工作。好的。
它们稍有不同,但与旧的扩展相比具有许多优势,包括对事务、存储过程和准备好的语句的API支持(从而提供了抵御SQL注入攻击的最佳方法)。PHP开发人员ulf wendel已经对这些特性进行了彻底的比较。好的。
hashphp.org有一个很好的关于从ext/mysql迁移到pdo的教程。好的。
I understand that it's possible to suppress deprecation errors by setting error_reporting in php.ini to exclude E_DEPRECATED:
Ok.
1
| error_reporting = E_ALL ^ E_DEPRECATED |
What will happen if I do that?
Ok.
是的,暂时可以禁止此类错误消息并继续使用旧的ext/mysql扩展。但您确实不应该这样做—这是开发人员发出的最后警告,即扩展可能不会与未来版本的PHP捆绑在一起(实际上,正如前面提到的,它已经从PHPv7中删除)。相反,您应该趁此机会立即迁移应用程序,以免为时已晚。好的。
还要注意,此技术将抑制所有E_DEPRECATED消息,而不仅仅是那些与ext/mysql扩展有关的消息:因此,您可能不知道会影响应用程序代码的其他即将发生的PHP更改。当然,只能通过使用php的错误控制运算符&mdash(即用@前缀相关行)来抑制问题表达式中出现的错误,但是这将抑制该表达式所引发的所有错误,而不仅仅是E_DEPRECATED错误。好的。
你应该怎么做?
您正在启动一个新项目。好的。
完全没有理由使用ext/mysql—选择另一种更现代的扩展,并从中获得好处。好的。
您有(自己的)遗留代码库,目前依赖于ext/mysql。好的。
执行回归测试是明智的:在确定了所有潜在的影响区域、围绕每个影响区域进行了计划,然后在登台环境中彻底测试解决方案之前,您真的不应该改变任何东西(尤其是升级PHP)。好的。
遵循良好的编码实践,您的应用程序是以松散集成/模块化的方式开发的,数据库访问方法都是在一个地方独立的,可以很容易地换成一个新的扩展。好的。
花半个小时重写这个模块,以使用另一个更现代的扩展;彻底测试。您可以稍后介绍进一步的改进,以获得他们提供的好处的回报。好的。
数据库访问方法分散在各处,不能轻易地换成新的扩展。好的。
现在考虑是否真的需要升级到php v5.5。好的。
您应该开始计划用另一种更现代的扩展来替换ext/mysql,以便获得它们所带来的好处;您也可以利用它将数据库访问方法重构为更模块化的结构。好的。
但是,如果您迫切需要立即升级php,您可能会暂时考虑抑制折旧错误:但首先要确定是否还有其他正在抛出的折旧错误。好的。
您正在使用依赖于ext/mysql的第三方项目。好的。
现在考虑是否真的需要升级到php v5.5。好的。
检查开发人员是否发布了与此特定问题相关的任何修复、解决方法或指导;或者,如果没有,通过提请他们注意,迫使他们这样做。如果您迫切需要立即升级php,您可能会暂时考虑抑制折旧错误:但首先要确保识别出任何其他也被抛出的折旧错误。好的。
执行回归测试是绝对必要的。好的。
好啊。
- 还请推荐/建议使用准备好的语句,,,多次我看到用户使用PDO或MySQLI查询的方式与MySQL相同,即使他们没有转义单引号,这是相当危险的。
- @nullpointer:它已经说"它们…提供…准备好的语句(从而提供击败SQL注入攻击的最佳方法)"。我真的不想在这个答案中给出参数化查询的例子,因为它与手头的问题并不真正相关;您认为如何才能更清楚?
- 如果你想要一个快速而肮脏的修复,只需在mysql_connect之前加上@就可以了。例如@mysql_connect(…);通过这种方式,您不必更改任何其他配置。使用剩余的mysql_u函数是可以的。只有mysql_connect()给出了这个消息。
- @bimapoudel:我已经说过了,在我的答案中——"当然,通过使用php的错误控制操作符(即,用@前置相关行)可以只抑制问题表达式中出现的错误,但是这将抑制该表达式所引发的所有错误,而不仅仅是E_DEPRECATED错误。"
- 添加错误报告(e_所有^e_已弃用);在顶部,这将解决您的问题。
- 我在我的项目中使用mysql_real_escape_string(),没有数据库(主要是为了防止?"跟着我说话"—来自用户生成的标题等的攻击。可悲的是,这个功能已经消失了。事实是?参数化查询不需要它"对我没有帮助。
- @弗兰基:如果数据库中没有这些用户生成的标题,您将把它们存储在哪里?你所指的"跟在我后面说话"攻击是什么?使用没有mysql数据库的mysql_real_escape_string()绝对不是打败任何东西的正确方法(因为它根据您的mysql数据库连接的字符集来转义字符串,而您没有!)。如果您试图阻止XSS攻击,则应该使用htmlentities()。对于任何其他攻击,请详细说明确切的威胁。
- @Eggyal-在边车里。为了重新准备,文列出了目录内容…是的,在某些情况下更合适。不管怎样,你是对的。htmlEntities()加上一些常规的字符串清理(清除字符和实体尝试,这在图像描述/headling中显然不需要)。老实说,在插入任何数据库之前,我也会使用这种卫生设施,作为第二道防线……