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

8 浏览
0 Comments

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

注意:这是一个关于处理PHP变量作用域的参考问题。请关闭所有符合这种模式的问题,将其视为重复问题。

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

0
0 Comments

变量的作用域是指变量在何处可访问以及出现"未定义变量"错误的原因。在PHP中,除了常见的局部变量和全局变量之外,还有一类特殊的变量,即超级全局变量。这些超级全局变量是数组,在任何作用域中都可以直接访问,无需使用global声明。

超级全局变量包括$_POST、$_GET、$_SESSION等。例如,下面的函数将打印出运行PHP脚本的用户的名称。这个变量在函数中可以直接使用,没有任何问题。

function test() {
    echo $_ENV["user"];
}

通常情况下,"全局变量是不好的"的原则在PHP中被修改为"全局变量是不好的,但超级全局变量是可以的",只要不滥用它们即可。(所有这些变量都是可写的,因此如果你真的很糟糕,可以使用它们来避免依赖注入。)

这些变量并不保证一定存在;管理员可以使用php.ini中的variables_order指令禁用其中的一些或全部变量,但这不是常见的行为。

当前的超级全局变量列表如下:

- $GLOBALS:当前脚本中的全局变量

- $_SERVER:服务器和执行环境的信息

- $_GET:通过URL的查询字符串传递的值,无论请求的HTTP方法是什么

- $_POST:通过application/x-www-form-urlencoded或multipart/form-data MIME类型的HTTP POST请求传递的值

- $_FILES:通过multipart/form-data MIME类型的HTTP POST请求传递的文件

- $_COOKIE:当前请求中传递的Cookie

- $_SESSION:PHP内部存储的会话变量

- $_REQUEST:通常是$_GET和$_POST的组合,但有时也包括$_COOKIES。其内容由php.ini中的request_order指令确定

- $_ENV:当前脚本的环境变量

原文参考:What is variable scope, which variables are accessible from where and what are "undefined variable" errors?

0
0 Comments

什么是静态变量?

静态变量与函数作用域内定义的普通变量不同,它在程序执行离开该作用域时不会丢失其值。下面是使用静态变量的示例:

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

如果我们没有使用静态变量来定义$counter,那么每次输出的值将与传递给函数的$num参数相同。使用静态变量可以在不需要额外解决方案的情况下构建这个简单的计数器。

静态变量的用途:

1. 在函数连续调用之间存储值。

2. 在递归调用之间存储值,当无法(或无需)将它们作为参数传递时。

3. 缓存通常最好只检索一次的值。例如,在服务器上读取不可变文件的结果。

技巧:

静态变量仅存在于局部函数作用域中。不能在其所定义的函数之外访问它。因此,可以确保它的值在下一次调用该函数之前保持不变。

静态变量只能定义为标量或标量表达式(自PHP 5.6起)。将其他值分配给它将不可避免地导致失败,至少在本文编写时是如此。不过,您可以在代码的下一行中这样做:

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 5.3中引入。简单来说,它们允许您限制函数作用域内一些变量的访问权限,只能使用另一个匿名函数来访问它们。在闭包中,变量可以模拟(或多或少地成功)面向对象编程中的概念,例如“类常量”(如果它们通过值传递给闭包)或“私有属性”(如果通过引用传递给闭包)。

后者实际上允许使用闭包来替代静态变量。使用哪种方法始终取决于开发人员决定,但应该提到的是,静态变量在处理递归时绝对有用,并且值得开发人员注意。

0
0 Comments

什么是“变量作用域”?

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

PHP中如何定义作用域?

非常简单:PHP有“函数作用域”。这是PHP中唯一存在的作用域分隔符。函数内部的变量仅在该函数内部可用。函数外部的变量在函数外部的任何地方都可用,但不能在任何函数内部使用。这意味着PHP中有一个特殊的作用域:全局作用域。在任何函数外部声明的变量都在全局作用域内。

作用域和包含的文件

文件边界不会分隔作用域。包含的代码与任何其他代码适用相同的规则:只有函数分隔作用域。对于作用域的目的,你可以将包含文件视为复制和粘贴代码。

关于函数内部的函数和类

每个新的函数声明引入一个新的作用域,就是这么简单。

作用域的作用是什么?

处理作用域问题可能看起来很烦人,但有限的变量作用域对于编写复杂的应用程序至关重要!如果你声明的每个变量都可以从应用程序的任何地方访问,你将会在变量上进行操作,而没有真正的方法来跟踪哪个改变了哪个。你可能只能为变量取有限的合理名称,可能想在多个地方使用变量“$name”。如果你只能在应用程序中有这个唯一的变量名,你将不得不使用非常复杂的命名方案来确保变量是唯一的,并且你没有从错误的代码片段更改了错误的变量。

跨作用域边界

正确的方法:传递变量进出

将变量作为函数参数显式传入这个作用域。仅仅查看这个函数,就清楚了它处理的值的来源在哪里。然后显式地返回一个值。调用者有信心知道函数将使用哪些变量以及其返回值的来源。

将变量的作用域扩展到匿名函数

匿名函数从其周围的作用域显式包含变量。请注意,这与全局作用域不同。

错误的方法:全局

正如之前所说,全局作用域有些特殊,函数可以明确地从全局作用域导入变量。这个函数使用并修改全局变量$foo。不要这样做!除非你真的真的真的知道自己在做什么,即使是这样:也不要这样做!

- 变量具有作用域,只有在同一作用域内的代码才能访问变量。

- PHP的作用域分为函数作用域和全局作用域。

- 文件边界不会分隔作用域,包含文件的代码与其他代码适用相同的规则。

- 函数内部的函数和类都有自己的作用域。

- 有限的变量作用域对于编写复杂的应用程序至关重要,可以避免变量混乱和命名冲突。

- 跨作用域边界的正确方法是显式传递变量进出。

- 将变量的作用域扩展到匿名函数可以使用use关键字。

- 不要使用全局作用域,除非你真的知道自己在做什么。

- 全局作用域应该尽可能避免使用,函数应该是无状态的。

- 传递变量引用与使用全局变量不同,它是一种显式传递可配置名称的方式。它可能会导致奇怪的副作用,只有在特定情况下才有意义。

- 全局作用域是错误的,永远不要使用它。

0