Reputation: 566
Using PHP 7.2, I have a class MyClass
that uses a trait MyFirstTrait
. It is defined like this:
class MyClass
{
use MyFirstTrait;
}
This MyFirstTrait
uses another trait MySecondTrait
. It is defined like this:
trait MyFirstTrait
{
use MySecondTrait;
}
MySecondTrait
does not use any other traits. It is defined like this:
trait MySecondTrait
{
}
If I define MyClass
first and then the traits (it does not matter in which order the traits are defined), an error is raised.
The file would be like:
// Not working
class MyClass { use MyFirstTrait; }
// These two lines can be swapped, the result is the same.
trait MyFirstTrait { use MySecondTrait; }
trait MySecondTrait { }
And the error raised is this:
Fatal error: Trait 'MyFirstTrait' not found in …
However, if I remove the nesting and remove the use
clause from MyFirstTrait
, the script runs without errors. The same happens if I define the traits first and then the class.
In the first case, the file would look like this:
// Working
class MyClass { use MyFirstTrait; }
trait MyFirstTrait { }
In the second case like this:
// Working
// These two lines can be swapped, the result is the same.
trait MyFirstTrait { use MySecondTrait; }
trait MySecondTrait { }
class MyClass { use MyFirstTrait; }
Why does the behavior change when the traits are nested?
It doesn’t make much sense to me, because in both cases, the used traits are defined later than they are referenced. When the nesting is removed and only single trait is used, there is no problem with the trait being defined after defining the class.
Upvotes: 2
Views: 989
Reputation: 522042
Logically, everything you refer to should be defined before you refer to it. There are some exceptions to this though. Taking a step back, a PHP file is interpreted in two steps:
Generally speaking, classes will be defined at runtime, meaning when the code is executed in the order it is written. Here you must have defined the trait you're going to use
in another trait first. However, some "simple" traits and classes can be generated and defined by the parser in the parsing step, so they will be available before runtime. That is purely a performance optimisation.
What exactly PHP regards as a "simple class/trait" is not something I would necessarily try to remember or count on, as the capabilities of the parser may expand from one version to another (for instance, at some point simple arithmetic expressions became supported for statements like static $foo = 4 + 2;
, which was previously a parse error).
Upvotes: 4