how to get used traits in php-class?

2019-04-03 12:10发布

问题:

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
  }
}

回答1:

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 )
{ 
    //...
}


回答2:

You can write it yourself, by using the ReflectionClass

$rc = new ReflectionClass('myClass');
$count = count($rc->getTraits());


回答3:

Just my 2 cents =)

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

Or with PHP > 5.6

in_array( CLASS_NAME::class, class_uses($model) )


回答4:

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



回答5:

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));
}


回答6:

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);
    ?>


回答7:

Short answer: you shouldn't. Traits are almost exactly copy and paste code. You don't NEED to know which traits are used, only on what the traits generate.

Answer I don't want to give: use ReflectionClass::getTraits. I'm not going to elaborate on this one.



标签: php oop traits