【问题标题】:What's with this Strange PHP Global Variable Scope?这个奇怪的 PHP 全局变量范围是怎么回事?
【发布时间】:2015-02-27 19:09:48
【问题描述】:

关于正确使用全局变量有很多问题,我将要求进一步澄清。许多可追溯到 3 年的帖子都问:“我如何使变量包含在函数中,在范围内是全局的。”

我的假设是他们的代码看起来像这样,因为没有给出明确的例子:

示例 1

#global_vars.php
<?
$my_global_var = "Hello World";
?>

#index.php
<?
function foo ()
{
   include_once ("global_vars.php");
   global $my_global_var;
   print ("my global var = [" . $my_global_var . "]<BR>");
   print ("complete<BR>");
}

foo ();
?>

哪个输出:

my global var = [] 
complete

示例 2

现在,如果“globals_var.php”更改为:

<?
global $my_global_var;
$my_global_var = "Hello World";
?>

结果是:

my global var = [Hello World]
complete

示例 3

现在,在您撰写并声明不建议使用这种类型的全局变量之前,全局变量有一些实际用途。而且大多数全局变量都封装在对象中作为常量或函数:

#global_vars.php
<?
class Globals 
{
    const my_global_var = "Hello World";

    public static $my_global_var2 = "Hello World";

    static function my_global_var3 ($newValue = null)
    {
        if (isset ($newValue))
            self::$my_global_var2 = $newValue;

        return (self::$my_global_var2);
    }
}
?>

#index.php
<?
function foo ()
{
    include_once ("global_vars.php");
    print ("my global var = [" . Globals::my_global_var . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3("Hi There") . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("complete<BR>");
}

foo ();
?>

输出是:

my global var = [Hello World]
my global var = [Hello World]
my global var = [Hi There]
my global var = [Hi There]
complete

示例 4

当然,此时“include_once”语句可以移到函数之外以获得相同的结果。

#index.php
<?
include_once ("global_vars.php");

function foo ()
{
    print ("my global var = [" . Globals::my_global_var . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3("Hi There") . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("complete<BR>");
}

foo ();
?>

输出:

my global var = [Hello World]
my global var = [Hello World]
my global var = [Hi There]
my global var = [Hi There]
complete

示例 5

在此示例中,文件包含在函数之外。一切都按照 PHP.net 文档的说明进行。

#global_vars.php
<?
$my_global_var = "Hello World";
?>

#index.php
<?
include_once ("global_vars.php");

function foo ()
{
    global $my_global_var;

    print ("my global var = [" . $my_global_var . "]<BR>");
    $my_global_var = "Hi There";
    print ("my global var = [" . $my_global_var . "]<BR>");
}

foo ();
?>

问题...

现在我的问题是......如果没有命名空间,为什么示例 1 中包含的变量不放在 $GLOBALS 中?而且,为什么这些变量不被视为函数范围的一部分?这是怎么回事?

示例 1 - GLOBALS / 定义变量

#index.php
<?

function foo ()
{
    include_once ("global_vars.php");

    global $my_global_var;

    print ("my global var = [" . $my_global_var . "]<BR>");

    print ("<pre>");
    print_r ($GLOBALS);
    print ("</pre>");

    print ("<pre>");
    print_r (get_defined_vars ());
    print ("</pre>");

}

foo ();
?>

输出是:

my global var = []

Array
(
    [_GET] => Array ()
    [_POST] => Array ()
    [_COOKIE] => Array  ( ... )
    [_FILES] => Array ()
    [GLOBALS] => Array
 *RECURSION*
    [my_global_var] => 
)

Array
(
    [my_global_var] => 
)

示例 2 - GLOBALS / 定义变量

my global var = [Hello World]

Array
(
    [_GET] => Array ()
    [_POST] => Array ()
    [_COOKIE] => Array  ( ... )
    [_FILES] => Array ()
    [GLOBALS] => Array
 *RECURSION*
    [my_global_var] => Hello World
)

Array
(
    [my_global_var] => Hello World
)

示例 6

根据“@kainaw”的回答,我更新了示例 1,以帮助其他人根据给出的示例了解这会是什么样子。假设“global_vars.php”中没有任何变化,但在“index.php”文件中,global 语句位于 include 语句之前。然后“my_gloval_var”被 PHP 认为是一个全局变量,并被初始化。

#global_vars.php
<?
$my_global_var = "Hello World";
?>

#index.php
<?
function foo ()
{
   global $my_global_var;

   include_once ("global_vars.php");

   print ("my global var = [" . $my_global_var . "]<BR>");
   print ("complete<BR>");
}

foo ();
?>

哪个输出:

my global var = [Hello World] 
complete

$GLOBALS 和 Define Vars 返回以下内容:

my global var = [Hello World]

Array
(
    [_GET] => Array ()
    [_POST] => Array ()
    [_COOKIE] => Array  ( ... )
    [_FILES] => Array ()
    [GLOBALS] => Array
 *RECURSION*
    [my_global_var] => Hello World
)

Array
(
    [my_global_var] => Hello World
)

【问题讨论】:

  • “关于正确使用全局变量有很多问题” 确实没有。 Just don't use globals.
  • 您的大多数示例都可以用 PHP 来回答,但实际上并没有“global”变量。默认情况下,一切都在本地范围内。只有一个共享范围。而所有global 关键字所做的就是使用对所述共享范围的引用来填充/覆盖局部变量表。

标签: php variables scope


【解决方案1】:

您遇到的主要问题是误解了使用“全局”命令时会发生什么。这简化了它:

function foo()
{
    $x = 1; // $x is local to foo() with a value of 1
    global $x; // $x is now the global (undeclared) variable
    echo $x; // Echos null
}

这就是您的第一个示例中发生的情况。您设置了一个变量,然后将该变量名切换为未声明的全局变量。简单的解决方案:

function foo()
{
    global $x; // $x is the global (undeclared) variable
    $x = 1; // $x (the global) now has a value of 1
    echo $x; // Echos 1
}
foo(); // Runs foo an echos 1.
echo $x; // Also echos 1 because global $x is 1.

在函数中声明全局变量是否合适是另一回事。这只是为了回答您关于“奇怪”行为的问题。就个人而言,我在 $GLOBALS 数组中注册了全局变量,并根据需要使用它。

【讨论】:

  • 在 BASIC、C 和 VB6 环境中长大,我习惯了全局变量是 GLOBAL。 =) Java 和 C# 更喜欢创建维护全局值的静态对象。 PHP 允许将所有这些混合在一起,当代码从基于函数的环境迁移到基于对象的环境迁移到命名空间的对象环境时意外偶然发现,这可能会变得非常混乱和令人沮丧 - 其中文件由两个类 auto 包含loader 和 include 语句。本练习的结论是……使用封装全局值的 Java 和 C# 方法。
  • 我更喜欢这样说:有许多语言旨在保护您免受自己的伤害。 PHP 不是其中之一。它旨在克服您犯的几乎所有(非语法)错误并继续做某事 - 也许不是您想要的,而是某事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 2018-03-01
  • 2012-01-19
  • 1970-01-01
相关资源
最近更新 更多