Trait Members

Trait Properties, Constants and static Members

Traits may declare properties, static members, abstract static methods and, since PHP 8.2, constants. Because the trait is copied, each using class gets its own static property. PHP 8.5 binds traits before the parent class, so when both declare a property or constant of the same name, the trait's wins; earlier versions raised a fatal error.

A per-class counter, a trait constant and the 8.5 binding orderPHP
<?php
trait Repository {
  public const int PAGE_SIZE = 20;                          // trait constants: PHP 8.2+
  private static int $created = 0;                          // one copy per using class
  public string $source = 'trait';
  abstract public static function table(): string;
  public static function make(): static { self::$created++; return new static(); }
  public static function created(): string { return static::table() . '=' . self::$created; }
}
class Entity { public string $source = 'parent'; }
final class Product extends Entity { use Repository;
  public static function table(): string { return 'products'; } }
final class Customer { use Repository;
  public static function table(): string { return 'customers'; } }
Product::make(); Product::make(); Customer::make();
echo Product::created(), ' ', Customer::created(), ' page ', Product::PAGE_SIZE, "\n";
echo 'source: ', (new Product())->source, "\n";               // trait beats parent in 8.5
try { echo Repository::PAGE_SIZE; } catch (Error $e) { echo $e->getMessage(), "\n"; }
Output
products=2 customers=1 page 20
source: trait
Cannot access trait constant Repository::PAGE_SIZE directly

Calling a static method on the trait itself (Repository::make()) has been deprecated since PHP 8.1. A class that redeclares a trait property must match its visibility, type, readonly and default, or PHP stops with a fatal error. PHP 8.5 can also mark a trait #[\Deprecated] (Built-In Attributes).