Why does using nested traits change PHP behavior?

放肆的年华 提交于 2019-12-22 18:17:43

问题


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.


回答1:


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:

  1. Tokenisation and parsing.
  2. Runtime execution of the parsed code.

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



来源:https://stackoverflow.com/questions/48417145/why-does-using-nested-traits-change-php-behavior

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!