My question is in three parts:
Does putting in a use
statement trigger the autoloader immediately, or does it wait until the class is used? (lazy-loading)
If autoloading isn't done in a lazy-load fashion, could that negatively affect performance?
Which pattern is best to follow, and why? PhpStorm shows "Unnecessary fully qualified name..." as a code issue when the use
statement isn't employed.
Here's an example class definition for a Laravel controller with a use
statement:
namespace App\Http\Controllers;
use Carbon\Carbon;
class FooController extends Controller
{
/**
* This action uses the Carbon class
*/
public function bar1()
{
return view('foo.bar1', ['now' => new Carbon()]);
}
/**
* This action does not use the Carbon class
*/
public function bar2()
{
return view('foo.bar2');
}
}
The same class without the use
statement:
namespace App\Http\Controllers;
class FooController extends Controller
{
/**
* This action uses the Carbon class
*/
public function bar1()
{
return view('foo.bar1', ['now' => new \Carbon\Carbon()]);
}
/**
* This action does not use the Carbon class
*/
public function bar2()
{
return view('foo.bar2');
}
}
1) The class is autoloaded when you perform a new Class()
statement.
2) see 1)
3) Which pattern is best to follow and why?:
I'd recommend to use use
because you might get into a situation where you have really long namespaces and your code will become unreadable.
From the php docs:
This example attempts to load the classes MyClass1 and MyClass2 from the files MyClass1.php and MyClass2.php respectively.
<?php
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
Namespaces are only an additional feature to organize classes.
EDIT: As @IMSoP pointed out in the comments, new is not the only time the autoloader is triggered. Accessing a class constant, static method, or static property will also trigger it, as will running class_exists.
The use
statement can be thought of like a C pre-processing macro, if you're familiar with those: it rewrites the current file at compile time to let you write a short name for a long class, function, or constant name. It doesn't trigger autoloading, as it doesn't care if a class exists or not.
For instance, if you write use Foo\Bar\Baz as X
, then everywhere that X
is mentioned as a class name, the PHP compiler rewrites that to mention Foo\Bar\Baz
instead. Only when code mentioning the class (e.g. new X
, X::FOO
, X::doSomething()
) is actually run does it see if there really is a class Foo\Bar\Baz
, and trigger the autoloader as necessary.
The common form use Foo\Bar\Baz
is just shorthand for use Foo\Bar\Baz as Baz
, assigning the alias Baz
to the class name Foo\Bar\Baz
.
As the manual points out the alias is only processed at compile time, so dynamic lookups will not use it. In the example above, class_exists('X')
will return false, but you can use class_exists(X::class)
to expand out the alias - the compiler will automatically substitute the full class name as a string, so at run-time, the expression will be class_exists('\Foo\Bar\Baz')
.
Whether use
statements make your code better is therefore entirely a matter of style: the intent is that your code will be more readable without the long fully-qualified class names, but it will make no difference to how the code actually runs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With