Как получить привычные черты в php-классе?
Есть ли какая-либо функция в PHP (5.4), чтобы использовать используемые черты как массив или аналогичный:
class myClass extends movingThings {
use bikes, tanks;
__construct() {
echo 'I\'m using the two traits:' . ????; // bikes, tanks
}
}
Ответы
Ответ 1
Чтобы легко получить используемые черты, вы можете вызвать 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 )
{
//...
}
Ответ 2
Вы можете написать это самостоятельно, используя ReflectionClass
$rc = new ReflectionClass('myClass');
$count = count($rc->getTraits());
Ответ 3
Только мои 2 цента =)
in_array( "CLASS_NAME", class_uses($model) )
Или с PHP > 5.6
in_array( CLASS_NAME::class, class_uses($model) )
Ответ 4
class-uses(<class>)
получит непосредственные черты <class>
, однако он не получит все унаследованные черты через родительские классы или черты признаков и т.д.
Если вам нужно получить абсолютно все унаследованные черты в классе, я бы рекомендовал прочитать комментарии в официальных документах здесь:
http://php.net/manual/en/function.class-uses.php
Ответ 5
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));
}
Ответ 6
Я хочу, чтобы это было полезно (благодаря 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);
?>
Ответ 7
Короткий ответ: вы не должны. Черты почти точно копируют и вставляют код. Вам НЕ НУЖНО знать, какие черты используются, только на том, что генерирует признаки.
Ответ. Я не хочу давать: используйте ReflectionClass:: getTraits. Я не собираюсь подробно останавливаться на этом.