PHP(5.4)中是否有可以将使用的 traits 获取为数组或类似的函数:
class myClass extends movingThings {
use bikes, tanks;
__construct() {
echo 'I\'m using the two traits:' . ????; // bikes, tanks
}
}
要轻松获取已使用的特性,您可以调用class_uses()
$usedTraits = class_uses(MyClass);
// or
$usedTraits = class_uses($myObject);
在检查可用功能时,我通常建议使用接口
。要向接口添加默认功能,您可以使用特性
。这样,您还可以从类型提示中受益。
通过实现一个接口来强制对象具有功能,然后使用特性来实现该接口的默认代码。
class MyClass
implements SomeInterface
{
use SomeTrait;
}
然后你可以通过以下方式检查接口:
$myObject = new MyClass();
if ($myObject instanceof SomeInterface) {
//...
}
仍然使用类型提示(type hinting);
function someFunction( SomeInterface $object )
{
//...
}
in_array( "CLASS_NAME", class_uses($model) )
如果使用 PHP > 5.6 版本
in_array( CLASS_NAME::class, class_uses($model) )
class-uses(<class>)
函数将获取<class>
的直接traits,但它不会获取通过父类或traits of traits等方式继承的所有traits...
如果您需要完全获取类中继承的所有traits,我建议阅读官方文档中的注释:
class_uses
和ReflectionClass->getTraits
在获取子类的特性时无法正常工作。
例如:
trait A {}
class Mother {
use A;
}
class Child extends Mother {}
var_dump(class_uses('Child')); // empty array
var_dump(class_uses('Mother')); // has A
我遇到了这个问题,所以编写了简单的代码来获取所有类的特性。
function all_class_uses($model)
{
$class = new ReflectionClass($model);
$traits = $class->getTraits();
while($parent = $class->getParentClass()) {
$traits += $class->getTraits();
$class = $parent;
}
return array_combine(array_keys($traits), array_keys($traits));
}
while
循环中 $traits += $class->getTraits();
应该改为 $traits += $parent->getTraits();
。 - Reinhold FürederI wish that will be useful (thanks to Maurice for interface usage):
interface IHaveHasTrait
{
public function has_trait($name);
};
trait THaveHasTrait
{
public function has_trait($name)
{
$classes = class_parents( $this );
$classes[] = get_class( $this );
foreach( $classes as $class ) {
foreach( class_uses( $class ) as $t ) {
if( $t === $name ) {
return true;
}
}
}
return false;
}
};
trait TLinkedListItem
{
use THaveHasTrait;
public $next;
public $prev;
};
class A implements IHaveHasTrait
{
use TLinkedListItem;
public $text;
public function __construct( $_text )
{
$this->text = $_text;
}
};
class B extends A{};
class C extends B{};
class LinkedList
{
public function insertItem( &$item, $position=0, $relative=false )
{
if( is_a( $item, 'IHaveHasTrait' ) ) {
echo $item->has_trait( 'TLinkedListItem' ) ? 'has' : 'not';
}
}
};
$a = new C('a');
$l = new LinkedList;
$l->insertItem($a);
?>
简短回答:你不应该这样做。Traits 几乎是复制粘贴的代码。你不需要知道使用了哪些 traits,只需要知道 traits 生成了什么。
我不想给出的答案:使用 ReflectionClass::getTraits。我不会详细解释这个。
get_class_methods()
,但是不存在get_class_traits()
。 - Mike B/review
时,你不应该使用“关闭所有”的方法。 - tereško