skip to Main Content

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

2

Answers


  1. Chosen as BEST ANSWER

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


  2. As commented earlier, I was not able to reproduce it. For future reference, my setup:

    • PhpStorm 2023.2 Build #PS-232.8660.205
    • PHP 8.2.8 (cli) (built: Jul 8 2023 07:10:21) (NTS)

    This means: It is likely with your older PhpStorm 2013.1.2 Build #PS-231.9011.38 you still need to mark the variable as global.

    Here a preview:

    $GLOBALS array with source locations

    Ctrl + Left Mouse Button (LMB) opens Choose Declaration pop-up menu. Both entries resolve to index.php locations:

    1. to $pageKat = "";
    2. to $pageKat = "foo";

    Type inference for global variable, here string

    Ctrl + Mouse Hover show type inference of the variable, it’s a string. Ctrl + LMB resolves to $pageKat = ""; in index.php.


    Full rundown:

    $ 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
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search