我问这个问题是因为某种 PHP(和 IDE)行为让我感到困惑,我想知道是否有人能理解它。如果您精通可变范围问题,那么这个问题适合您!
所以我有一个 index.php 文件,其中我定义了一个名为
$pageKat = "";
的变量,然后根据某些条件为其分配一个值。
然后我
require
index.php 中的另一个名为 _actual-content.php 的 php 文件。
<?php # index.php
...
$pageKat = "";
...
if (...) {
$pageKat = "foo";
}
...
require __DIR__ . '/_actual-content.php';
我的 _actual-content.php 的前 11 行如下所示:
<div id="theMan">
<header>
<?php if ($GLOBALS["pageKat"] == "home") echo "<h1 class='h1Home'>"; ?>[REDACTED-HTML]<?php if ($pageKat == "home") echo "</h1>"; ?>
</header>
<nav class="headerMenu" aria-label="Haupt-Navigation">
<ul>
<?php generateMainMenu($pageKat); print_r($pageKat); ?>
</ul>
</nav>
[REDACTED-HTML]
部分是为了让一切更容易阅读。实际上只有简单的静态 HTML 可以生成徽标。它与手头的问题无关,我已对其进行了编辑以整理代码块。
现在,如您所见,我在这里访问 $pageKat 三次(如果算上调试的话,实际上是四次
print_r
)。
这是奇怪的部分:
在第一个
<?php ... ?>
块中,我使用 $GLOBALS 数组来访问 pageKat (正如人们所期望的那样,这是必要的)。我首先尝试访问 $pageKat,但这不起作用,因为 $pageKat 不在 _actual-content.php 的范围内(再次,如预期的那样)。
在第二个和第三个
<?php ... ?>
块中,奇怪的是,我能够直接访问$pageKat。 IDE (PhpStorm) 将其标记为“未定义”(下面有一条红色波浪线,再次:如预期的那样)...但它可以工作。如果 $pageKat 为“home”,则 if
语句将被正确处理,并且 </h1>
HTML 将被回显。 generateMainMenu() 函数也被正确调用并且工作起来就像一个魅力, print_r() 转储 $pageKat 的值......一切都很好。
所以我的问题是:为什么?为什么它有效? (我尝试检查在通过 $GLOBALS 访问一次作用域内的全局变量后是否可以“直接”访问它,但这似乎不在 PHP 规范中。)
再次,我问这个问题是因为我试图理解变量作用域是如何工作的,而这种行为对我来说看起来完全奇怪。我很好奇到底发生了什么,所以如果有人能启发我,我将非常感激。
(请不要让这个问题退化为关于全局变量有多糟糕的讨论。我是个菜鸟,我知道这一点,我一直很喜欢全局变量,我会为它们的存在权而奋斗,直到我的最后一口气。;)这不是重点。)
答案是: $pageKat 实际上是一个全局变量,OP(我)只是假设它不是因为 IDE 的波浪线将其标记为“未定义”。我会展现自己的。
正如之前评论的那样,我无法重现它。供将来参考,我的设置:
这意味着:对于较旧的 PhpStorm 2013.1.2 Build #PS-231.9011.38,您可能仍然需要将该变量标记为全局变量。
这里是预览:
完整概要:
$ cd ~/PhpstormProjects/hakre/sos/so76843156
$ cat composer.json
{
"name": "sos/so76843156",
"require": {
"php": "8.2"
},
"extra": {
"composer.json": {
"offical": {
"url": "https://getcomposer.org/schema.json",
"refs": [
{
"The composer.json schema": {
"href": "https://getcomposer.org/doc/04-schema.md#the-composer-json-schema",
"summary": "This chapter will explain all of the fields available in composer.json."
}
}
]
}
}
}
}
$ ~/opt/PhpStorm/bin/phpstorm.sh --version
CompileCommand: exclude com/intellij/openapi/vfs/impl/FilePartNodeRoot.trieDescend bool exclude = true
PhpStorm 2023.2
Build #PS-232.8660.205
$ php8.2 --version
PHP 8.2.8 (cli) (built: Jul 8 2023 07:10:21) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.8, Copyright (c) Zend Technologies
with Zend OPcache v8.2.8, Copyright (c), by Zend Technologies
with Xdebug v3.2.1, Copyright (c) 2002-2023, by Derick Rethans
$ tree
.
├── _actual-content.php
├── composer.json
├── index.php
└── README.md