Skip to content
Advertisement

PHP7 const defined within a require (external file) within a conditional (if) is working – why?

While debugging a large body of code, I came across the following that was completely unrelated to my debugging. I did spend an inordinate amount of time Google searching for a plausible explanation:

The declaration of a const, within a function, within a conditional (if), within a require of an external file included. NOTE: this was NOT defined as part of a class construct!!

Since this const is defined within the context of a conditional, making it run-time? vs compile/parse-time, this should (IMHO) have given an error, but not only was there no error, but the code has been running perfectly in production for over three years!

Would love to hear expert explanations, or even a clue to what I am obviously missing!

Q1. Why is constant _DEFITEM not giving an error?

Q2. Why is constant _DEFITEM working even though it was not defined using define?

Thank you, in advance, and especially to JS, and for the wonderful work this community has done over the last decade!

REFERENCE:

PHP Manual

If an include() is conditional, will PHP include the file even if the condition is not met?

https://wordpress.stackexchange.com/questions/143439/conditionally-include-files-in-functions-php

CODE: Simple stub with a function that gets called, checks a passed-by-value parameter for “SAVE”, conditionally including the (ALWAYS available) save module file, and then calling its main function. The included (require) save module file has the const declaration at the top.

Contrived, but accurate code representation below! Ellipses represent other code

//  main_stub3.php     php file processing client request (included within a main page/script)
<?php
function list_view_save_proc_stub3 (fn_param1, fn_param2...)  {
...
if ("VIEW" === fn_param2)  {
   ...
}
else
if ("SAVE" === fn_param2)  {
   ...
   require _INC . proj_save_module_file.php;           //  _INC is a global constant (path)
   sv_mod_fn ();
}
else
   ...
}  //  END fn list_view_save_proc_stub3
//  END main_stub3.php


//  proj_save_module_file.inc   include file that contains a const declaration and a function
const _DEFITEM = [ 'it_id' => 0, 'it_name' => '', ... ];   //  about ~50 items in array

function sv_mod_fn ()  {
//  some std error checking, building of a row, db connectivity and insertion +
//  message output to client
...
}

Advertisement

Answer

People often talk about PHP as a “scripting” or even “interpreted” language, but like most modern languages it does have distinct compilation and execution steps. A lot of the details aren’t often relevant, but are crucial to your misunderstanding here.

PHP compiles files when they are first needed; it can also (via the OpCache extension) cache the result of this compilation. Importantly, it always compiles a single file at a time, regardless of how that file is used. So everything that happens at compile-time is based on what can be known just looking at that single file.

Once a file is compiled, it can be executed any number of times (either within the same request, or later by getting it from OpCache memory). So everything that happens at execution-time can know everything about the current context it’s running in.

To understand your code, you then only need to know two things:

  • const is evaluated at compile-time
  • require is evaluated at execution-time

What the manual means when it says const can’t be used in a conditional is that when a file is compiled, the definition becomes part of the compiled code, unconditionally. Every program that file is part of will include that constant definition. This is different from define, which is compiled a bit like a function call – it becomes a marker saying “when you get to this point in the execution of the program, define this constant”.

However, compiling the file doesn’t make it part of your program. To actually make it part of your program, you use require (or its relatives), at execution-time.

Only when the require line is executed does that compiled file become part of your running program. It might be compiled just in time to execute, or fetched from OpCache having been compiled hours ago, but either way it is executed only when that require is actually reached. That require can be optional, so you might decide to include a different file depending on the day of the week, or at random, or based on user input.

So as far as PHP’s concerned, the const definition is unconditionally compiled into a unit of code that is conditionally included in your program.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement