how to get used traits in php-class?

2019-04-03 11:51发布

Is there any function in PHP (5.4) to get used traits as array or similar:

class myClass extends movingThings {
  use bikes, tanks;

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

标签: php oop traits
7条回答
闹够了就滚
2楼-- · 2019-04-03 12:28

I 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);
    ?>
查看更多
做个烂人
3楼-- · 2019-04-03 12:29

To easily get the used traits you can call class_uses()

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

General recommendations

When checking for available functionality, I would generally recommend to use interfaces. To add default functionality to an interface you would use traits. This way you can also benefit from type hinting.

Force an object having functionality by implementing an interface and then use a trait to implement default code for that interface.

class MyClass 
    implements SomeInterface 
{
    use SomeTrait;
}

Then you can check the interface by;

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

And still use type hinting;

function someFunction( SomeInterface $object )
{ 
    //...
}
查看更多
Deceive 欺骗
4楼-- · 2019-04-03 12:37

You can write it yourself, by using the ReflectionClass

$rc = new ReflectionClass('myClass');
$count = count($rc->getTraits());
查看更多
兄弟一词,经得起流年.
5楼-- · 2019-04-03 12:42

Just my 2 cents =)

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

Or with PHP > 5.6

in_array( CLASS_NAME::class, class_uses($model) )
查看更多
Summer. ? 凉城
6楼-- · 2019-04-03 12:51

class-uses(<class>) will get the immediate traits of <class> however it won't get all inherited traits by way of parent classes or traits of traits etc...

If you need to get absolutely all inherited traits on a class I would recommend reading the comments in the official docs here:

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

查看更多
该账号已被封号
7楼-- · 2019-04-03 12:52

class_uses and ReflectionClass->getTraits will not work if you want to get traits from child class.

Example.

trait A {}

class Mother {
    use A;
}

class Child extends Mother {}

var_dump(class_uses('Child'));  // empty array
var_dump(class_uses('Mother')); // has A

I have this problem so I write simple code for get all traits from classes.

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));
}
查看更多
登录 后发表回答