参考:什么是变量作用域,哪些变量可以从哪里访问,什么是“未定义变量”错误?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (15)

注意:这是处理PHP中变量作用域的参考问题。请关闭适合此模式的许多问题中的任何一个作为此问题的重复。

什么是PHP中的“可变范围”?一个.php文件中的变量是否可以在另一个中访问?为什么我有时会得到“未定义的变量”错误?

提问于
用户回答回答于

什么是“可变范围”?

变量有一个有限的“范围”,或“他们可以访问的地方”。仅仅因为你写$foo = 'bar';一次的地方在你的应用程序并不意味着你可以参照$foo到处其他的应用程序中。该变量$foo具有一定的范围,在该范围内它是有效的,并且只有在同一范围内的代码才能访问该变量。

在PHP中如何定义一个范围?

非常简单:PHP具有功能范围。这是PHP中唯一的范围分隔符。函数内部的变量只能在该函数内部使用。函数外部的变量在函数之外的任何地方都可用,但不在任何函数内部。这意味着PHP中有一个特殊的范围:全局范围。在任何函数之外声明的任何变量都在此全局范围内。

例:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;
}

$foo全球范围内,$baz本地范围内myFunc。只有内部的代码myFunc可以访问$baz。只有外部 代码才能myFunc访问$foo。两者都无法访问另一个:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;

    echo $foo;  // doesn't work
    echo $baz;  // works
}

echo $foo;  // works
echo $baz;  // doesn't work

范围和包含的文件

文件边界不分隔范围:

a.php只会

<?php

$foo = 'bar';

b.php

<?php

include 'a.php';

echo $foo;  // works!

include适用于任何其他代码的d代码也适用相同的规则:仅适用于function单独的作用域。出于范围的目的,可能会想到包含复制和粘贴代码等文件:

c.php

<?php

function myFunc() {
    include 'a.php';

    echo $foo;  // works
}

myFunc();

echo $foo;  // doesn't work!

在上面的例子中,a.php被包含在里面myFunc,里面的任何变量a.php只有局部函数的作用域。仅仅因为它们似乎在全球范围内a.php并不一定意味着它们,它实际上取决于在哪个上下文中包含/执行代码。

那么函数和类中的函数呢?

每一个新的function声明都引入了一个新的范围,就是这么简单。

(匿名)函数

function foo() {
    $foo = 'bar';

    $bar = function () {
        // no access to $foo
        $baz = 'baz';
    };

    // no access to $baz
}

$foo = 'foo';

class Bar {

    public function baz() {
        // no access to $foo
        $baz = 'baz';
    }

}

// no access to $baz

什么是适用范围?

处理范围问题似乎很烦人,但变量范围有限对编写复杂的应用程序至关重要!如果你声明的每个变量都可以在你的应用程序的其他任何地方使用,那么你将会遍历你的变量,而没有真正的方法来追踪什么变化。只有很多明智的名字可以给你的变量,你可能想$name在多个地方使用变量“ ”。如果您的应用只能使用一次这个唯一的变量名称,那么将不得不求助于真正复杂的命名方案,以确保变量是唯一的,并且不会从错误的代码块中更改错误的变量。

注意:

function foo() {
    echo $bar;
}

如果没有范围,上述功能会做什么?哪里$bar来的?它有什么状态?它是否已经初始化?你每次都要检查吗?

穿越范围界限

正确的方法:将变量传入和传出

function foo($bar) {
    echo $bar;
    return 42;
}

该变量$bar作为函数参数显式进入该范围。只要看看这个函数,就可以很清楚它的工作原理来自哪里。然后它显式返回一个值。调用者有信心知道函数将使用哪些变量以及返回值的来源:

$baz   = 'baz';
$blarg = foo($baz);

将变量的范围扩展为匿名函数

$foo = 'bar';

$baz = function () use ($foo) {
    echo $foo;
};

$baz();

匿名函数明确包含$foo其周围的范围。请注意,这与全局范围不一样。

错误的方法: global

如前所述,全局范围有点特殊,函数可以从中明确地导入变量:

$foo = 'bar';

function baz() {
    global $foo;
    echo $foo;
    $foo = 'baz';
}

该函数使用并修改全局变量$foo不要这样做! (除非你真的真的真的知道你在做什么,即使如此:不要!)

这个函数的所有调用者看到的都是这样的:

baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!

没有迹象表明这个功能有任何副作用,但它确实存在。随着一些功能不断修改并需要一些全局状态,这很容易变得混乱。你希望函数是无状态的,只对它们的输入起作用,并且返回定义的输出,然而很多时候你称之为它们。

用户回答回答于

变量的范围是其定义的上下文。大多数情况下,所有PHP变量只有一个范围。这个单一的范围跨越了包含和必需的文件。例如:

<?php
$a = 1;
include 'b.inc';
?>

这里的$a变量将在包含的b.inc脚本中可用。但是,在用户定义的函数中引入了本地函数作用域。在函数内部使用的任何变量缺省地局限于本地函数作用域。例如:

<?php
$a = 1; /* global scope */ 

function test()
{ 
    echo $a; /* reference to local scope variable */ 
} 

test();
?>

此脚本不会产生任何输出,因为echo语句引用了$ a变量的本地版本,并且在此范围内尚未分配一个值。您可能会注意到,这与C语言有点不同,因为C中的全局变量可自动用于函数,除非被本地定义明确覆盖。这可能会导致一些问题,人们可能会无意中更改全局变量。在PHP中,全局变量必须在函数中声明为全局变量,如果它们将在该函数中使用。

扫码关注云+社区