小编典典

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

all

注意:这是一个在 PHP 中处理变量范围的参考问题。请关闭符合此模式的许多问题中的任何一个作为此问题的副本。

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


阅读 55

收藏
2022-08-19

共1个答案

小编典典

什么是“可变范围”?

变量具有有限的“范围”,或“可以访问它们的位置”。 仅仅因为您在应用程序的某个地方 编写$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

范围和包含的文件

文件边界 不分隔 范围:

一个.php

<?php

$foo = 'bar';

b.php

<?php

include 'a.php';

echo $foo;  // works!

适用于included
代码的规则与适用于任何其他代码的规则相同:仅适用于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?!?!!

没有迹象表明此功能有任何 副作用 ,但确实有。这很容易变成一团乱麻,因为一些函数不断修改 并需要 一些全局状态。你希望函数是 无状态
的,只作用于它们的输入并返回定义的输出,不管你调用它们多少次。

您应该尽可能避免以任何方式使用全局范围;最肯定的是,您不应该将变量从全局范围“拉”到本地范围中。

2022-08-19