在PHP中使用'global'关键字

4
我在学习模式下,对PHP非常陌生,所以我正在使用一个代码示例。请原谅我在这里使用了“global”,但我想理解PHP变量作用域。
以下是我的Globals.php:
<?php 
     global $db_server;
   // other code not shown
?>

这是connectToDb.php文件:
<?php
      require_once 'myGlobals.php';

      // no declared functions in this file, all inline code
      $db_server = mysql_connect(.....);
      mysql_select_db( "theDatabase", $db_server);
?>

这是addDbRecords.php文件:
<?php
       require_once 'myGlobals.php';

       // other inline code.....
       doAddDeleteRecord($db_server);

function doAddDeleteRecord($db_server)
{
  //global $db_server;

  if( !mysql_query($query, $db_server))
   {
         // handle the error...
   }
 }
?>

这是index.php文件:
<?php
      require_once 'myGlobals.php';
      require_once 'connectToDb.php';
      require_once 'addDbRecords.php';

     // this is simplified, just trying to show that everything in inline code
 ?>

这里出现了问题。当我在addDbRecords.php文件中调用doAddDeleteRecord($db_server)时,mysql_query(.., $db_server, ...)中的$db_server无效——它是null——这是错误信息:
“Warning: mysql_query() expects parameter 2 to be resource, null given in C:\xampp\htdocs\addDbRecords.php on line 29”
因此,我尝试在doAddDeleteRecord()中使用'global'声明(如上所述)——但没有任何改变。mysql_query(...)仍然会因为$db_server的值为NULL而失败。
我知道mysql_connect(....)有效,因为其他代码成功地从我的数据库中取出了所有记录(使用SELECT),并且现有记录在浏览器中正确显示。
因此,在我看来,$db_server被声明为'global'应该意味着$db_server的作用域是这样的,一旦在所有文件中的文件范围内调用mysql_connect(...),$db_server将成为与我的数据库建立的有效连接。
我只想学习有关php作用域的知识,而不是OOAD或其他任何东西(目前)。为什么这里$db_server()为空?

3
为什么?这里的大多数回答似乎声称这是一个谬论。 - Lightness Races in Orbit
1
如果您仍在使用旧的mysql_接口函数,则无需传递连接句柄。如果只有一个已打开,则会隐式使用它。(除非您传递null值。) - mario
1
@require_once: 这确实可能是问题的原因,因为 myglobals.php 脚本只被加载了 一次,而 OP 可能希望它被多次包含。 (然而,一般的不建议使用并没有意义。) - mario
1
@mario:除了OP没有在函数内部使用include[_once]之外,其他都正确。OP是在每个文件的顶部包含它,无论如何切割,仍需要使用global修饰符才能在函数内使用这些变量。 - Chris Eberle
回想起来,我认为你的代码中根本不需要使用 global。因为你总是从全局作用域引用变量。 - Lightness Races in Orbit
显示剩余8条评论
2个回答

5

那么,你有:

<?php 
     global $db_server;
   // other code not shown
?>

你需要在必要的地方包含以下内容:

require_once 'myGlobals.php';
// other inline code.....
doAddDeleteRecord($db_server);

问题在于,如果你已经在其他地方包含了'myGlobals.php',那么它在这里就不会被包含。因此,你无法保证全局变量会被引入作用域。

相反,应该这样写:

require 'myGlobals.php';
// other inline code.....
doAddDeleteRecord($db_server);

或者采用更好的方法,只需:
// other inline code.....
doAddDeleteRecord($GLOBALS['db_server']);

在函数内部使用 global 关键字可以告诉 PHP 使用全局作用域的变量,而不是创建一个仅在函数内可见的私有作用域变量。 - Fosco
我不同意,我现在有一个四个文件的设置正在工作,并且它们全部使用require_once()。第一次执行语句global $db_server就足够了。 - Darien
@Darien:只有在全局范围内始终包含该文件时才有效。 - Lightness Races in Orbit
实际上,我的回答问题在于,在他的任何文件中都根本不需要使用 global - Lightness Races in Orbit
这也是一个问题,但我的意思是 global $foo; 的副作用在全局范围内(毫无意义地)执行时也是全局的……只要它已经被早期包含了一次,你就不需要再次包含它。这和你在全局范围内定义函数或类一样。 - Darien

1

我认为存在作用域隐藏的问题;也就是说,您正在使用相同的名称($db_server)作为全局变量和函数本地变量。函数本地作用域会隐藏全局变量名称。如果您有一个全局变量,则不需要将其传递给函数;如果您确实需要传递,请不要使用相同的名称。


我把变量名改成了“function doAddDeleteRecord($db_server_global_scope)”,并在调用mysql_query(..,$db_server_global_scope,...)时使用了db_server_global_scope——没有变化。仅供参考,我之前没有在任何地方使用'global',只是添加了它来尝试修复这个问题。如果我在所有地方删除'global',问题还是一样的。注意:调用doAddDeleteRecord($db_server_global_scope)失败的原因是我的“add record”表单返回到文件时——由于POST造成重新输入代码,这会使db_server为空吗? - wantTheBest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接