24

PHP(5.4)中是否有任何函数可以将使用的特征作为数组或类似的:

class myClass extends movingThings {
  use bikes, tanks;

  __construct() {
    echo 'I\'m using the two traits:' . ????; // bikes, tanks
  }
}
4

7 回答 7

36

要轻松获取使用的特征,您可以调用class_uses()

$usedTraits = class_uses(MyClass);
// or
$usedTraits = class_uses($myObject);

一般建议

在检查可用功能时,我通常建议使用interfaces. 要将默认功能添加到您将使用的界面traits。这样你也可以从类型提示中受益。

通过实现接口强制对象具有功能,然后使用特征来实现该接口的默认代码。

class MyClass 
    implements SomeInterface 
{
    use SomeTrait;
}

然后您可以通过以下方式检查界面;

$myObject = new MyClass();
if ($myObject instanceof SomeInterface) {
    //...
}

并且仍然使用类型提示;

function someFunction( SomeInterface $object )
{ 
    //...
}
于 2014-03-07T12:37:25.613 回答
12

您可以使用ReflectionClass自己编写

$rc = new ReflectionClass('myClass');
$count = count($rc->getTraits());
于 2012-11-29T19:43:52.347 回答
8

只是我的 2 美分 =)

in_array( "CLASS_NAME", class_uses($model) ) 

或 PHP > 5.6

in_array( CLASS_NAME::class, class_uses($model) )
于 2015-11-17T13:19:13.950 回答
2

class_usesReflectionClass->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));
}
于 2016-10-18T09:58:40.747 回答
2

class-uses(<class>)将获得直接的特征,<class>但是它不会通过父类或特征的特征等方式获得所有继承的特征......

如果您需要获得一个类的所有继承特征,我建议您阅读官方文档中的评论:

http://php.net/manual/en/function.class-uses.php

于 2015-10-29T23:58:23.120 回答
1

我希望这会有用(感谢 Maurice 的界面使用):

    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);
    ?>
于 2014-09-17T20:56:37.813 回答
-2

简短的回答:你不应该。特征几乎完全是复制和粘贴代码。您不需要知道使用了哪些特征,只需要知道特征生成的内容。

答案我不想给出:使用ReflectionClass::getTraits。我不打算详细说明这一点。

于 2012-11-29T19:44:34.423 回答