Php 参考:什么是变量范围,哪些变量可以从何处访问,哪些是;未定义变量";错误?

Php 参考:什么是变量范围,哪些变量可以从何处访问,哪些是;未定义变量";错误?,php,scope,Php,Scope,注意:这是一个在PHP中处理变量作用域的参考问题。请将符合此模式的许多问题中的任何一个作为此问题的副本关闭 什么是PHP中的“变量范围”?一个.php文件中的变量是否可以在另一个文件中访问?为什么有时会出现“未定义变量”错误?什么是“变量范围”? 变量的“范围”或“可访问的位置”有限。就因为你写了$foo='bar'在应用程序中的某个位置一次并不意味着您可以从应用程序中的任何其他位置引用$foo。变量$foo有一个特定范围,在该范围内它是有效的,并且只有同一范围内的代码才能访问该变量 如何在PH

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

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

什么是“变量范围”? 变量的“范围”或“可访问的位置”有限。就因为你写了
$foo='bar'
在应用程序中的某个位置一次并不意味着您可以从应用程序中的任何其他位置引用
$foo
。变量
$foo
有一个特定范围,在该范围内它是有效的,并且只有同一范围内的代码才能访问该变量

如何在PHP中定义作用域? 非常简单:PHP具有函数作用域。这是PHP中唯一存在的范围分隔符。函数中的变量仅在该函数中可用。函数外的变量在函数外的任何地方都可用,但在任何函数内都不可用。这意味着PHP中有一个特殊的作用域:全局作用域。在任何函数之外声明的任何变量都在此全局范围内

例子: 范围和包含的文件 文件边界不分隔作用域:

a、 php

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

函数和类中的函数呢? 每一个新的
函数
声明都会引入一个新的范围,就是这么简单

(匿名)函数中的函数 班级 什么是好的范围? 处理范围问题可能看起来很烦人,但是有限的变量范围对于编写复杂的应用程序来说是必不可少的如果您声明的每个变量都可以从应用程序中的任何其他地方获得,那么您将无法跟踪变量的变化。您可以为变量指定的合理名称太多,您可能希望在多个位置使用变量“
$name
”。如果你只能在你的应用程序中使用这个唯一的变量名一次,你就必须求助于非常复杂的命名方案,以确保你的变量是唯一的,并且你没有从错误的代码中更改错误的变量

注意:

function foo() {
    echo $bar;
}
如果没有作用域,上面的函数会做什么?
$bar
来自哪里?它有什么州?它甚至被初始化了吗?你每次都要检查吗?这是不可维护的。这让我们想到

跨越范围边界 正确的方法:传入和传出变量 变量
$bar
作为函数参数显式进入此范围。只要看看这个函数,就可以清楚地知道它使用的值来自何处。然后它显式返回一个值。调用者有信心知道函数将使用哪些变量以及其返回值来自何处:

$baz   = 'baz';
$blarg = 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有一个众所周知的
static
关键字,该关键字在面向对象的PHP中广泛用于定义静态方法和属性,但应该记住,
static
也可以在函数内部用于定义静态变量

什么是“静态变量”? 静态变量不同于函数作用域中定义的普通变量,因为当程序执行离开此作用域时,它不会丢失值。让我们考虑下面的使用静态变量的例子:

function countSheep($num) {
 static $counter = 0;
 $counter += $num;
 echo "$counter sheep jumped over fence";
}

countSheep(1);
countSheep(2);
countSheep(3);
结果:

1 sheep jumped over fence
3 sheep jumped over fence
6 sheep jumped over fence
2 sheep jumped over fence
5 sheep jumped over fence
9 sheep jumped over fence
如果我们定义了
$counter
而没有
static
,那么每次回显的值都将与传递给函数的
$num
参数相同。使用
static
可以构建这个简单的计数器,而无需额外的解决方法

静态变量用例
  • 在后续函数调用之间存储值
  • 在没有方法(或没有方法)时在递归调用之间存储值 目的)将其作为参数传递
  • 缓存通常最好检索一次的值。对于 例如,在服务器上读取不可变文件的结果
  • 技巧 静态变量仅存在于局部函数作用域中。不可能 在已定义的函数之外访问。所以你可以 确保它将保持其值不变,直到
    function foo() {
        echo $bar;
    }
    
    function foo($bar) {
        echo $bar;
        return 42;
    }
    
    $baz   = 'baz';
    $blarg = foo($baz);
    
    $foo = 'bar';
    
    $baz = function () use ($foo) {
        echo $foo;
    };
    
    $baz();
    
    $foo = 'bar';
    
    function baz() {
        global $foo;
        echo $foo;
        $foo = 'baz';
    }
    
    baz(); // outputs "bar"
    unset($foo);
    baz(); // no output, WTF?!
    baz(); // outputs "baz", WTF?!?!!
    
    function countSheep($num) {
     static $counter = 0;
     $counter += $num;
     echo "$counter sheep jumped over fence";
    }
    
    countSheep(1);
    countSheep(2);
    countSheep(3);
    
    1 sheep jumped over fence
    3 sheep jumped over fence
    6 sheep jumped over fence
    
    function countSheep($num) {
      static $counter = 0;
      $counter += sqrt($num);//imagine we need to take root of our sheep each time
      echo "$counter sheep jumped over fence";
    }
    
    2 sheep jumped over fence
    5 sheep jumped over fence
    9 sheep jumped over fence
    
    class SomeClass {
      public function foo() {
        static $x = 0;
        echo ++$x;
      }
    }
    
    $object1 = new SomeClass;
    $object2 = new SomeClass;
    
    $object1->foo(); // 1
    $object2->foo(); // 2 oops, $object2 uses the same static $x as $object1
    $object1->foo(); // 3 now $object1 increments $x
    $object2->foo(); // 4 and now his twin brother
    
    <?php
    function test() {
        echo $_ENV["user"];
    }