Kub*_*cki 32
虽然没有什么能阻止您使用instanceof特征,但推荐的方法是将特征与接口配对.所以你有:
class Foo implements MyInterface
{
use MyTrait;
}
Run Code Online (Sandbox Code Playgroud)
在哪里MyTrait实施MyInterface.然后你检查界面而不是像这样的特征:
if ($foo instanceof MyInterface) {
...
}
Run Code Online (Sandbox Code Playgroud)
你也可以输入提示,你不能用特征:
function bar(MyInterface $foo) {
...
}
Run Code Online (Sandbox Code Playgroud)
如果您绝对需要知道某个类是使用某个特征还是实现,您只需向该接口添加另一个方法,该方法将根据实现返回不同的值.
Rod*_*ias 28
您可以使用class_uses函数来获取类所使用的所有特征的数组.
然后检查此数组是否具有与您正在测试的特征名称相同的密钥.
如果是这样,那么你的班级正在使用你的特质.如果没有,那么就没有使用它.
它不是很干净,可能不适合您的情况.但另一种方法是检查对象或类是否实现了Trait的方法(通常不会使用Trait覆盖现有方法)
if (method_exists($my_object, 'MyTraitSpecificMethod')){
...
}
Run Code Online (Sandbox Code Playgroud)
我刚刚发现 Laravel 如何解决这个问题,并想在这里分享。它使用class_usesunder ,但遍历所有父级以递归地找到所有特征。
它定义了一个名为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;
}
Run Code Online (Sandbox Code Playgroud)
你可以这样使用它:
in_array(MyTrait::class, class_uses_recursive($class));
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看他们如何使用它来检查模型是否实现 SoftDeletes 特征:
public function throughParentSoftDeletes()
{
return in_array(SoftDeletes::class, class_uses_recursive($this->throughParent));
}
Run Code Online (Sandbox Code Playgroud)