The execution of a PHP script happens in two phases: first the script is compiled and, if there are no syntax errors, the compiler generates a sequence of so-called "opcodes". Then, the interpreter kicks in and starts the script execution; this means it takes the opcodes one by one, interprets them and performs the operations encoded by them.
Only the main script is compiled before starting the execution, the files included (using one of the include
functions) are compiled during the execution.
Let's see what happens with your script.
include_once
The include/include_once/require/require_once
statements generate code that tells the interpreter: "stop the execution of the current script here, load and compile this file and, if it doesn't contain syntax errors, execute its code before continuing this script".
That's it, the included files are not read during the compilation phase of the main script but only when (and if) they are needed during runtime. In this fragment of code:
if (false) {
include 'a.php';
}
the content of file a.php
is never read; even more, the interpreter doesn't even care if the file exists or not. It starts caring about a.php
only when the include
statement is about to be executed but this never happens because of the if (false)
test.
use
The use
statement is used to create an alias. Such an alias is only an agreement between the programmer and the compiler, the compiler doesn't generate any code for it.
By using the statement:
use Symfony\Component\HttpFoundation\Request;
the programmer tells the compiler: "hey, I want you to know that later in this file when you find the token Request
I mean \Symfony\Component\HttpFoundation\Request
but I prefer to use only Request
instead because it's shorter".
The use
statements don't let any trace in the generated code. They do not exist at runtime. The code:
use Symfony\Component\HttpFoundation\Request;
$request = new Request();
is the same as:
$request = new \Symfony\Component\HttpFoundation\Request();
The same code is generated for them; during the compilation, the first form is "transformed" into the second one.
The autoloader
The content of file vendor/autoload.php
is (probably) the autoloader generated by Composer. An autoloader is a callable (function or class method) registered using spl_autoload_register()
that is executed by the interpreter when the code reaches a reference to an unknown class. The autoloader receives the full class name (with namespace) and its purpose is to make the class available. It usually knows where to find the class (in a file). Multiple autoloaders can be registered and the interpreter calls them one by one until the class becomes available or all of them fail.
How it runs
Let's replace the alias in your variants of code and see what we get.
Variants #1 and #2 produce the same code:
include_once __DIR__ . '/vendor/autoload.php';
$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
echo $request->getMethod();
During runtime:
- the
include_once
statement loads and registers the autoloader;
-
$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals()
- the class \Symfony\Component\HttpFoundation\Request
is not known, the interpreter invokes the autoloader that includes the file that declares the class; then the method createFromGlobals
of the class is executed and it returns an object of type \Symfony\Component\HttpFoundation\Request
;
-
$request
is not null
and its class implements the method getMethod()
; the method is called, the value it returns is displayed by echo
, everybody is happy.
Variant #3:
$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
include_once __DIR__ . '/vendor/autoload.php';
echo $request->getMethod();
How it runs:
Variant #4:
include_once __DIR__ . '/vendor/autoload.php';
$request = Request::createFromGlobals();
echo $request->getMethod();
The alias is not replaced because it is declared after it is used.
During runtime: