【问题标题】:PHP, an odd variable scope?PHP,一个奇怪的变量范围?
【发布时间】:2011-04-21 11:11:15
【问题描述】:

这更多是关于为什么然后是“如何做”的问题,但它已经让我烦恼了几天。目前我正在使用 CodeIgniter 做一些工作,并暂时从 Ruby 回到 PHP,这让我对以下范围魔法感到困惑。

<?php $query = $this->db->get('articles', 2);
        if ($query->num_rows() > 0)
        {
           foreach ($query->result_array() as $row)
           {
              $data[] = $row; # <-- first appearance here
           }
        return $data; # <--- :S what?!
        } 

如您所见,我并不完全是 PHP 专家,但本地范围的想法让我感到困扰,即在 foreach 循环之外,变量是“可用的”。所以我在一个视图中尝试了这个:

<?php

    if($a==1)
    {
    $b = 2;
    }
    echo $b;
?>

这会导致错误消息:

Message: Undefined variable: b

PHP 手册讲述了本地范围,但我仍然想知道为什么会发生这种情况,以及是否有我不知道的特殊规则。它让我害怕:)

感谢您分享想法,

【问题讨论】:

  • 仅当 $a 为 1 时才在第二个示例中创建变量。由于 $a 不存在(PHP 实际上在此处引发错误),因此不会创建 $b。在第一个示例中,所有条件都已满足,因此创建了 $data 并将其用作返回值。
  • 第二个例子更多的是澄清/过度简化大括号外的 $b 是可访问的 - 正如其他答案所述,大括号不定义变量的范围。而且,我不知道:)
  • 我认为这已经过时了,或者可能是严格的问题。您的第二个示例适用于我并打印 2。我正在使用 5.4.16 并关闭 STRICT
  • @Dennis,它不起作用。你认为它有效是因为 Shyam 已经更正了所有其他人一直在谈论的代码。我进行了回滚,以便每个人都在同一页面上。

标签: php scope


【解决方案1】:

只有函数才能创建新的本地范围。花括号本身不会。花括号只是其他语言结构(ifwhileforeach)的辅助结构

无论您在哪里访问本地范围内的任何变量都无关紧要。本地范围是幕后的隐式字典(请参阅get_defined_vars)。您可能会通过访问以前未定义的变量来获得调试通知,但仅此而已。

在您的具体示例中,您甚至只是在全局范围内操作。

【讨论】:

  • 第一句话让人看得一清二楚!谢谢!
  • 酷。还有一个正式的语言语义术语,但我不记得了。 ://
  • @mario, Citation needed for "花括号只是其他语言结构的辅助构造"....
【解决方案2】:

foreach 不会在 PHP 中创建任何变量作用域,因此如果变量在 foreach 之外可用是很自然的

对于第二个问题,$a 不等于1,因此$b 未初始化并在您访问外部时引发通知。如果您将值 1 分配给 $a 并对其进行测试,您会想知道通知会消失。

这和范围没什么两样。

【讨论】:

  • 第二个例子不是问题,更像是我所期望的行为的视角(我对 PHP 语言缺乏经验)。正如其他答案所述,花括号没有定义变量范围。不过,谢谢你的回答:)
【解决方案3】:

见:http://php.net/manual/en/language.variables.scope.php

在 php 中,花括号不一定为变量定义新的范围。 (你的第一个例子)

在您的第二个示例中, $b 仅在特定条件下设置。因此,如果不满足此条件,则可能是“未定义”。

【讨论】:

  • 感谢您的链接和您的回答!
【解决方案4】:

Shyam,您使用的是脚本语言,而不是 C++。对于像 PHP 或 JavaScript 这样的脚本语言来说,每个代码块没有不同的范围是很典型的。相反,整个函数只有一个作用域。如果您考虑第一个示例,这实际上非常方便,但您显然需要小心,如第二个示例所示。

【讨论】:

  • PL 包含范围机制是一个很好的设计(除了丑陋的call_user_func(function(){ }))。为什么“脚本语言通常不会为每个代码块设置不同的范围”?
【解决方案5】:

$a 是否等于 1?如果不是 $b=2 将永远不会被评估!

【讨论】:

    【解决方案6】:

    实际上,您的第一种方法也应该给您一个错误。

    您正在使用尚未声明为数组的变量。我不明白你为什么没有得到错误。

    PHP 没有块作用域,所以它是在 IF 还是 FOREACH 内部都无关紧要。如果它在方法内部可用,您可以在方法内部使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-02
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多