【问题标题】:How to check if a class uses a trait in PHP?如何检查一个类是否使用 PHP 中的特征?
【发布时间】:2017-09-14 11:33:07
【问题描述】:

请注意,一个特征可能会使用其他特征,因此该类可能不会直接使用该特征。并且该类也可以从使用该特征的父类继承。

这是一个可以在几行内解决的问题还是我必须做一些循环?

【问题讨论】:

标签: php traits


【解决方案1】:

class_uses() 函数将返回一个数组,其中包含该类使用的所有特征的名称,并将通过将类名或实例传递给它来工作....但是,您需要“递归”通过继承树来获取所有使用的特征,以及通过每个特征

编辑

请注意,stealz at op dot pl 提供了一个示例函数,展示了如何在链接的 PHP 文档页面的 cmets 部分中执行此递归

【讨论】:

    【解决方案2】:

    如果有人在使用 Laravel 框架时遇到这个问题,它有一个名为 class_uses_recursive() 的辅助函数。

    https://laravel.com/docs/8.x/helpers#method-class-uses-recursive

    【讨论】:

      【解决方案3】:

      在特质列表中检查你的特质:

      $usingTrait = in_array(
          MyTrait::class, 
          array_keys((new \ReflectionClass(MyClass::class))->getTraits())
      );
      

      如果MyClass 使用MyTrait,则返回真或假

      【讨论】:

      • 为什么不只是class_uses 而不是反射?
      • $usingTrait = in_array(MyTrait::class, class_uses(MyClass::class))
      【解决方案4】:

      解决此问题的另一种方法是使用接口来定义对您的特征的期望。然后,您使用“instanceof SomeInterface”而不是进行反射或鸭式打字。

      【讨论】:

        【解决方案5】:

        如果您只想检查类,您可以使用class_uses,它将返回一个仅由该类使用的所有特征的数组

        in_array(SoftDeletes::class, class_uses(Model::class), true) //return boolean
        

        如果你想检查类或其父母是否使用 trait 使用 class_uses_recursive

        in_array(SoftDeletes::class, class_uses_recursive(Model::class), true) //return boolean
        

        【讨论】:

          【解决方案6】:

          以下函数来自http://php.net/manual/en/function.class-uses.php,ulf 的评论。完美运行。

          function class_uses_deep($class, $autoload = true)
          {
              $traits = [];
          
              // Get traits of all parent classes
              do {
                  $traits = array_merge(class_uses($class, $autoload), $traits);
              } while ($class = get_parent_class($class));
          
              // Get traits of all parent traits
              $traitsToSearch = $traits;
              while (!empty($traitsToSearch)) {
                  $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
                  $traits = array_merge($newTraits, $traits);
                  $traitsToSearch = array_merge($newTraits, $traitsToSearch);
              };
          
              foreach ($traits as $trait => $same) {
                  $traits = array_merge(class_uses($trait, $autoload), $traits);
              }
          
              return array_unique($traits);
          }
          

          【讨论】:

            【解决方案7】:

            通常,检查您打算使用的 API 部分是否存在是一个足够好的替代品。
            method_exists ( mixed $object , string $method_name ) : bool

            此外,正如@MeatPopsicle 所提到的,特征通常与(标记)接口结合使用。

            【讨论】:

              【解决方案8】:

              这就是我的工具类中的内容

              static function 
              isTrait( $object, $traitName, $autoloader = true )
              {
                  $ret = class_uses( $object, $autoloader ) ;
                  if( is_array( $ret ) )
                  {
                      $ret = array_search( $traitName, $ret ) !== false ;
                  }
                  return $ret ;
              }
              

              【讨论】:

              • 我的眼睛在流血,请检查 PSR2
              【解决方案9】:

              我在这个话题上遇到了一些问题,我写了一个解决方案,我想与大家分享。通过使用new ReflectionClass($objectOrClass),您可以使用实例方法getTraits()。问题是它只会返回 $objectOrClass 的特征数组,而不是从特征或扩展类继承的特征。

              解决办法如下:

              /** @return ReflectionClass[] */
              function get_reflection_class_traits( ReflectionClass $reflection, array $traits = [] ): array {
                  if ( $reflection->getParentClass() ) {
                      $traits = get_reflection_class_traits( $reflection->getParentClass(), $traits );
                  }
              
                  if ( ! empty( $reflection->getTraits() ) ) {
                      foreach ( $reflection->getTraits() as $trait_key => $trait ) {
                          $traits[$trait_key] = $trait;
                          $traits = get_reflection_class_traits( $trait, $traits );
                      }
                  }
              
                  return $traits;
              }
              
              // string|object $objectOrClass Either a string containing the name of the class to reflect, or an object.
              $objectOrClass = //...
              $reflection = new ReflectionClass( $objectOrClass );
              $all_traits = $this->get_reflection_class_traits( reflection );
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-10-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-11-08
                • 2018-11-13
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多