Есть ли какая-либо функция в PHP (5.4), чтобы использовать используемые черты как массив или подобное:
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);
При проверке доступных функций я бы рекомендовал использовать interfaces
. Чтобы добавить функциональность по умолчанию к интерфейсу, вы должны использовать traits
. Таким образом, вы также можете воспользоваться подсказкой типа.
Принудите объект, имеющий функциональность, реализуя интерфейс, а затем используйте черту для реализации кода по умолчанию для этого интерфейса.
class MyClass implements SomeInterface { use SomeTrait; }
Затем вы можете проверить интерфейс;
$myObject = new MyClass(); if ($myObject instanceof SomeInterface) { //... }
И все еще используйте тип намека;
function someFunction( SomeInterface $object ) { //... }
Вы можете написать это самостоятельно, используя ReflectionClass
$rc = new ReflectionClass('myClass'); $count = count($rc->getTraits());
Просто мои 2 цента =)
in_array( "CLASS_NAME", class_uses($model) )
Или с PHP> 5.6
in_array( CLASS_NAME::class, class_uses($model) )
class-uses(<class>)
получит непосредственные черты <class>
однако он не получит все унаследованные черты через родительские классы или черты признаков и т. д. …
Если вам нужно получить абсолютно все унаследованные черты в классе, я бы рекомендовал прочитать комментарии в официальных документах здесь:
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)); }
Хотелось бы, чтобы это было полезно (спасибо Морису за использование интерфейса):
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); ?>
Короткий ответ: вы не должны. Черты почти точно копируют и вставляют код. Вам НЕ НУЖНО знать, какие черты используются, только на том, что генерирует признаки.
Ответ, который я не хочу давать: используйте ReflectionClass :: getTraits . Я не собираюсь подробно останавливаться на этом.