What is the proper way to check if a class uses a certain trait?
While nothing stops you from using instanceof with traits, the recommended approach is to pair traits with interfaces. So you'd have:
class Foo implements MyInterface
{
use MyTrait;
}
Where MyTrait is an implementation of MyInterface.
Then you check for the interface instead of traits like so:
if ($foo instanceof MyInterface) {
...
}
And you can also type hint, which you can't with traits:
function bar(MyInterface $foo) {
...
}
In case you absolutely need to know whether a class is using a certain trait or implementation, you can just add another method to the interface, which returns a different value based on the implementation.
I just found how Laravel solves this and thought I'd share it here. It uses class_uses beneath but goes through all the parents to find all the traits recursively.
It defines a helper function called class_uses_recursive:
function class_uses_recursive($class)
{
if (is_object($class)) {
$class = get_class($class);
}
$results = [];
foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) {
$results += trait_uses_recursive($class);
}
return array_unique($results);
}
function trait_uses_recursive($trait)
{
$traits = class_uses($trait);
foreach ($traits as $trait) {
$traits += trait_uses_recursive($trait);
}
return $traits;
}
And you can use it like this:
in_array(MyTrait::class, class_uses_recursive($class));
You can see how they use it to check if a model implements the SoftDeletes trait here:
public function throughParentSoftDeletes()
{
return in_array(SoftDeletes::class, class_uses_recursive($this->throughParent));
}
You can use class_uses function to get an array of all the traits used by a class.
Then you check if this array has a key with the same name of the trait you're testing for.
if so, then your class is using your trait. If not, then it's not using it.
It's not really clean and may not be the right solution for your case. But an alternative is to check if the object or class implements a method of the Trait (as usually you don't overwrite existing methods with Trait)
if (method_exists($my_object, 'MyTraitSpecificMethod')){
...
}