Compiled trait

Structure of the generated trait#

PHP traits are compiled into corresponding CLR types. The sample below depicts a PHP trait and resulting CLR type decompiled into C# language.

<?php
trait T {
  function foo() { return 1; }
  // ...
}
[PhpTrait]
[PhpType("T", "index.php")]
public sealed class T<TSelf> where TSelf : class {

  // 'TSelf' is type of class that uses this trait.

  public T(Context ctx, TSelf @this) { ... }

  public long foo() { return 1L; }

  // ...
}

Traits are special case of types. The compiler can generate classes with multiple inheritance using traits. The sample below shows a PHP class using a trait and the resulting CLR type decompiled into C# language.

The compiled class then automatically declares all the members of the trait. Their implementation calls the trait members internally.

<?php
class X {
  use T;
}
[PhpType("X", "index.php")]
public class X {
  private readonly T<X> <>trait_T; // holds instance of the trait

  public X(Contex <ctx>) {
    this.<>trait_T = new T<X>(<ctx>, this);
  }

  public virtual long foo() {
    return this.<>trait_T.foo();
  }
}

Constructors#

The trait constructor is always in the form below:

  • public .ctor(Context ctx, TSelf @this)
    The constructor initializes the trait with instance to $this and current context. This constructor is well known to the compiler and it is used by classes that use the trait.

Attributes#

The type is annotated with [PhpTypeAttribute] and [PhpTraitAttribute]. The attribute contains fully qualified PHP class name and relative file path where it was declared.