required_once() 中的变量未定义但可与 require() 一起使用,为啥?

Posted

技术标签:

【中文标题】required_once() 中的变量未定义但可与 require() 一起使用,为啥?【英文标题】:variable from required_once() not defined but works with require(), why?required_once() 中的变量未定义但可与 require() 一起使用,为什么? 【发布时间】:2017-03-25 12:46:18 【问题描述】:

我对编程很陌生,必须制作一个与 php7 兼容的网站。 我不想更改更多我需要的代码,所以我决定将旧的已弃用(不再工作)mysql_ 更改为新的mysqli_ db-connection。

到目前为止,一切都运行良好,但在一些脚本中,我遇到了 db-connection-script 的 require_once 问题,它包含在脚本的顶部并且运行良好,但在同一脚本中的“函数”中包含db-connection-file 和它的变量不可用,即使我再次“include_once”它。

但如果我只是“包含()”它,它会再次起作用。我的问题是,为什么? 据我了解,在没有“include_once”的情况下多次包含一个文件可能会导致问题,所以我真的需要帮助来理解这个问题。

index.php:

<?php
require_once('../../Connections/db.php');
mysqli_select_db($dbcon, $dbname);
$query = "SELECT x, y FROM dbtable WHERE z";

效果很好,但在同一个文件中:

function pruefe_datum($datum)

if (!function_exists("GetSQLValueString")) 
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
require_once('../../Connections/db.php');
$theValue = mysqli_escape_string($dbcon, $theValue);
  

抛出:

注意:未定义变量:dbcon 和警告:mysqli_escape_string() 期望参数 1 为 mysqli,给定 null

【问题讨论】:

你是否在同一个文件中使用了两次require_once('../../Connections/db.php'); 您忘记显示$dbcon 变量的初始化 您认为_once 位是什么意思? 这就是问题所在,据我所知,值并未取消。应该执行,但不是。 @Jon Stirling 我知道如果它已经包含它就不会再包含了。我想知道的是,为什么函数中没有连接变量? @Rocktale 我想你刚刚回答了你自己的问题。该文件已包含在其他地方,因此该文件不会包含在函数范围内。 【参考方案1】:

您正在使用 require_once('../../Connections/db.php');

函数之外。因此 Connections/db.php 已经包含在内,因此即使您再次通过 require_once 包含它,它也无法在函数中使用。

见difference

解决方案:删除第二个 require 调用,而是将变量传递给函数:GetSQLValueString($theValue, $dbcon, ....)

【讨论】:

所以 a 解决方案是删除第二个 require 调用,而是将变量传递给函数:GetSQLValueString($theValue, $dbcon, ....) @Martin 正确。包括在答案中。谢谢。 是的,它包含在函数之外,但为什么现在函数内部没有可用的连接?我的意思是,整个脚本适用于较旧的 mysql,但不适用于 mysqli。 @Rocktale 您的$dbcon 变量在文件中可用,但不在函数的本地范围内 除非我将它作为@Martin 所说的参数传递,不是吗?是的,这对我来说听起来很合乎逻辑。好吧,在不传递参数时,是否仍然可以像使用“mysql_”一样使用“mysqli_”进行最后一个连接?我猜不是,只是好奇。【参考方案2】:

假设您在此函数之前没有关闭数据库连接,以下应该可以工作:

function pruefe_datum($datum)
    if (!function_exists("GetSQLValueString")) 
        function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
            global $dbcon; 
            $theValue = mysqli_escape_string($dbcon, $theValue);
        
     

这是一个范围问题。 $dbcon 变量在函数中不存在,第二个 require_once 被忽略且不需要。

【讨论】:

是的,我想这是解决它的最佳方法。我知道这里的其他一些人也已经说明了范围问题,感谢他们所有人!正如我所说,我还在学习。并且旧的“mysql_”-方法不一定需要传递给它的连接,它只需要最后一个可用或尝试打开一个新的,但是“mysqli_”-方法需要一个作为参数传递的连接,这样似乎这就是为什么它可以与旧的“mysql_”一起使用但不适用于我对“mysqli_”的更改的原因。非常感谢! @Rocktale NO.对于这种代码构造,使用global 是个坏主意。它将两个值(函数和数据库变量)结合得太紧密了,很容易导致您出现复杂性问题。 read more about why 。 varlogtim 的这个答案不是最佳实践。 More here @Martin 好的,我知道这可能会导致设置全局变量出现问题,感谢您的链接。我仍然不明白我还能做些什么来解决我的问题?如前所述,我不想更改我需要的更多代码,但我也希望它能够工作,并且还想了解如何认为事情是正确完成的。那么,我应该将连接变量作为参数传递给我需要它的每个函数,而不是将其声明为全局变量吗?或者我还能做什么? 如果你有很多使用数据库连接的函数,那么你应该简单地创建一个数据库Class,其中包含这些函数并在类中有一个变量来保存数据库连接。然后,班级中的每个人都可以访问它。关于其他说明;如果您想做最佳实践但又不想编辑代码,那么这有点关键,因为您需要不断开发和重新设计非最佳实践代码,所以有点像想说话但不想说话想要张开嘴.... :-/ @Rocktale 进一步说明,假设您有一组用于处理客户篮子的函数,然后您可以将这些函数全部设置到 basket 类中,并且在该篮子类中您可以定义 (在构造中)一个包含数据库连接的变量,然后从类中的任何函数(称为方法)中使用它。 $basket = new BasketClass($dbcon); 其中dbcon 然后作为变量保存到篮子类中,可以通过$this-&gt;basketDbVar 访问

以上是关于required_once() 中的变量未定义但可与 require() 一起使用,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

用于 PHP 的 Google API 客户端中的 required_once 问题

对“dlsym”的未定义引用

指定 IP 地址时 syslog NG 未启动,但可作为全部捕获并写入文件设置

视图页面laravel中的未定义变量[关闭]

刀片视图中的laravel未定义变量

Laravel 7 组件中的未定义变量