php - 引用:什么是变量作用域?哪些变量可从何处访问?什么是“ undefined variable ”错误?

标签 php scope

注意:这是在PHP中处理变量范围的参考问题。请关闭所有适合此模式的问题,以作为该问题的重复。


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

最佳答案

什么是“可变范围”?

变量具有有限的“作用域”或“可从其访问的位置”。仅仅因为您在应用程序中的某个位置写过一次$foo = 'bar';并不意味着您可以从应用程序内的其他任何地方引用$foo。变量$foo在一定范围内有效,并且只有相同范围内的代码才能访问该变量。

如何在PHP中定义范围?

很简单:PHP具有功能范围。那是PHP中存在的唯一一种范围分隔符。函数内部的变量仅在该函数内部可用。函数外部的变量在函数外部的任何位置可用,但在任何函数内部均不可用。这意味着PHP中有一个特殊的作用域:全局作用域。在任何函数外部声明的任何变量都在此全局范围内。

例:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;
}


$foo在全局范围内,$bazmyFunc内的局部范围内。只有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中包含了myFunca.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 - 引用:什么是变量作用域?哪些变量可从何处访问?什么是“ undefined variable ”错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34907454/

相关文章:

php - symfony2 实体验证正则表达式 a-z A-Z 0-9

C++ 公共(public)变量作用域混淆

c++ - 为什么在 C++ 类指针声明中使用 'struct' 关键字

php - 解析错误: Help me solve my php error

php - PHP 中的 UTF-8 和 IsAlpha()

php - 类似于 Actionscript 中 PHP 的 __call()

php - 全局覆盖 symfony2.1 上的 NotBlank Constraint Message?

perl - 如何在perl中在同一范围内重新声明变量?

c++ - 在函数中填充容器避免段错误

javascript - javascript 中的 if 语句和作用域