trait_exists
Checks whether a trait with the given name is defined, optionally running autoloaders first.
trait_exists(string $trait, bool $autoload = true): bool- Added in PHP 5.4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$trait | string | The trait name, fully qualified with its namespace and no leading backslash. |
$autoloadoptional | bool= true | Whether registered autoloaders may be invoked to try to load the trait. |
Return value
booltrue if the trait is defined, false otherwise.
Errors
Does not throw by itself, but with $autoload left at true a registered autoloader may throw while trying to load the name.
trait_exists() checks that a trait has been declared. Traits live in the same name table as classes and interfaces, so a name can only be one of the three — and the matching *_exists() function is the only way to tell which kind you have.
When to reach for it
- Guarding a
traitdeclaration in a file that may be included more than once, or that ships a polyfill only when a package's own trait is absent. - Deciding at bootstrap whether an optional package that provides mixin behaviour is installed.
- Tooling — static analysers, code generators, test helpers — that must classify a name before emitting code for it.
What trips people up
Traits are not types. You cannot ask instanceof or is_a() about them, and trait_exists() only says the trait was declared, never that any class uses it. For that second question use class_uses(), remembering it returns only the traits used directly by that class — traits pulled in by a parent class or nested inside another trait need a manual walk up class_parents().
As with class_exists(), the name is not resolved against use statements, so pass the fully qualified string or MyTrait::class. And pass false for $autoload, which otherwise defaults to true, when merely probing, so a strict autoloader cannot fatal on a name that was never meant to load.
Example
When to use it
- Declaring a polyfill trait only when the real package has not already defined one.
- Detecting at bootstrap whether an optional package supplying a behaviour trait is installed.
- Classifying a discovered name as class, interface, enum, or trait in a code generator.
Frequently asked questions
What is the difference between trait_exists and class_exists?
They check different name kinds: class_exists() is true only for classes, trait_exists() only for traits. A single name can never be both, because classes, interfaces, enums and traits share one namespace.
How do I check whether a class uses a trait?
Use class_uses(), which returns the traits applied directly to that class. For traits inherited from a parent, loop over class_parents() and merge the results.
Can I use instanceof with a trait?
No. Traits are not types, so instanceof and is_a() always return false for a trait name. Only class_uses() answers that question.
More examples
Declaring a trait only once
The guard makes the file safe to include twice, which matters for polyfill files loaded outside an autoloader. The trait is then used normally and the check reports true afterwards.
<?php
if (!trait_exists('Cacheable', false)) {
trait Cacheable {
public function cacheKey(): string { return static::class . ':1'; }
}
}
class Page { use Cacheable; }
echo (new Page())->cacheKey(), "\n";
var_dump(trait_exists('Cacheable', false));Traits used through a parent class
class_uses('Article') is empty because the trait is applied on the parent, so inherited traits need a walk over class_parents(). The final is_a() is false, confirming that traits never behave as types.
<?php
trait Sluggable {}
class Base { use Sluggable; }
class Article extends Base {}
var_dump(trait_exists('Sluggable'));
print_r(class_uses('Article')); // empty - not used directly
print_r(class_uses('Base'));
var_dump(is_a(new Article(), 'Sluggable'));
Discussion