Search code examples
phpscopephpstorm

Totally weird PHP variable scope behaviour (also weird IDE behaviour) – can anyone make sense of this?


I'm asking this question b/c a certain PHP (and IDE) behaviour confuses me, and I was wondering if anyone can make sense of it. If you are proficient in variable scope questions, then this question is for you!

So I have an index.php file in which at one point I define a variable called $pageKat = ""; and later assign it a value based on certain conditions.

Then I require another php file from index.php called _actual-content.php.

<?php # index.php

...

$pageKat = "";

...

if (...) {
    $pageKat = "foo";
}

...

require __DIR__ . '/_actual-content.php';

The first 11 lines of my _actual-content.php look like this:

<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>

The [REDACTED-HTML] part is there to make it all easier readable. There's really just plain static HTML there that generates a logo. It has nothing to do with the question at hand and I've redacted it to de-clutter the code block.

Now, as you can see, I am accessing $pageKat three times here (actually four times, if you count the debugging print_r).

Here's the weird part:

  • In the first <?php ... ?> block, I'm using the $GLOBALS array to access pageKat (as one would expect is necessary). I first tried to access $pageKat, but that doesn't work, as $pageKat is not in the scope of _actual-content.php (again, as expected).

  • In the second and third <?php ... ?> block, though, weirdly, I AM able to access $pageKat directly. The IDE (PhpStorm) marks it as "undefined" (with a red wavy line beneath it, again: as expected)... but it works. The if statement is processed correctly and the </h1> HTML is echoed if $pageKat is "home". The generateMainMenu() function is also called correctly and works like a charm, the print_r() dumps $pageKat's value... all fine.

So my question is: Why? Why does it work? (I tried checking whether you can access a global variable inside a scope "directly" after having accessed it once via $GLOBALS, but this does not seem to be in PHP specs.)

Again, I'm asking this question because I'm trying to wrap my head around how variable scope works, and this behaviour looks completely odd to me. I'm curious what the heck is going on, so if anyone can enlighten me, I'd be very thankful.

(Please let's not have this question degenerate into a discussion about how bad global variables are. I'm a total noob and I know it, I've always loved global vars, and I will fight for their right to exist until my last breath. ;) This is not the point here.)


Solution

  • The answer is: $pageKat actually is a global var and as such defined in the included .php, OP (me) simply assumed it wasn't because of the wavy red line by the IDE that marked it as "undefined". I'll show myself out.

    • PhpStorm 2023.1.2 Build #PS-231.9011.38

    For final clarification, here's a screenshot of what global variables in included files look like in PhpStorm 2023.1.2:

    Screenshot of PhpStorm 2023.1.2 marking a global variable in an included .php file as "undefined" and offering to "Add 'global [variable]'"

    (Disclaimer: Demonstrating here with a different global variable than the one mentioned in the original q.)

    Additional info: Clicking "Add 'global $[variable]'" causes PhpStorm to add global$[variable] (w/o whitespace before $) to the beginning of the current file...