【问题标题】:Laravel get Model by Table NameLaravel 通过表名获取模型
【发布时间】:2021-08-11 11:14:12
【问题描述】:

有没有办法通过表名获取模型?

例如,我有一个“用户”模型,它的表定义为protected $table = "users"

现在,我要做的是通过等于“用户”的表名获取模型。

这个函数更像是Model::getTable();的逆向

我到处搜索,但找不到解决方案,也许我可能遗漏了一些简单的东西?

编辑

我正在构建类似于 API 的东西:

Route::get('/{table}', 'ApiController@api');
Route::get('/{table}/filter', 'ApiController@filter');
Route::get('/{table}/sort', 'ApiController@sort');
Route::get('/{table}/search', 'ApiController@search');

所以在地址栏中,例如当我搜索“用户”时,我可以直接点击 URL:

api/users/search?id=1

然后在控制器上,类似:

public function search(){
  // get all the params

  // get the model function
  $model = //function to get model by table name

  // do some filtering, then return the model
  return $model;
}

【问题讨论】:

  • 可以告诉我们您想做什么吗?因为当我看到这样的问题时,我想到的就是继承和依赖倒置之类的东西
  • @AchrafKhouadja 我已经编辑了我的问题。谢谢
  • 请记住,格式正确的问题会产生更好的答案,我希望您能找到您正在寻找的答案

标签: php laravel


【解决方案1】:

也许这样的事情会帮助你:

$className = 'App\\' . studly_case(str_singular($tableName));

if(class_exists($className)) {
    $model = new $className;
}

【讨论】:

  • 谢谢伊戈尔 :) 如果我的表名与模型类的名称相同,这是可能的。
  • 但是在其他方面你不能在不创建实例的情况下获得模型类的 $table,因为 $table 变量是受保护的,你不能静态访问它。如果不更改核心模型类,您将无法做到这一点
  • 我明白你的意思。嗯,所以 Laravel 没有类似 CoreModel::getModelByTableName(string)
  • 不,它不知道这些类甚至是模型,它们只是类。
  • Laravel 6 - 我的以下工作:使用 Illuminate\Support\Str; ..... $className = 'App\\' 。 str::study(str::singular($tableName)); if(class_exists($className)) { $model = new $className; }
【解决方案2】:

studly_case()str_singular() 是已弃用的函数。

你可以使用Illuminate\Support\Str门面。

$className = 'App\\' . Str::studly(Str::singular($tableName));

【讨论】:

    【解决方案3】:

    您必须确定要为哪个表名调用哪个类。 我看到了两种方法来做到这一点。

    按照@IgorRynkovoy 的建议使用 Laravel 的模型命名约定

    使用某种字典

    public function search($tableName)
    {
        $dictionary = [
            'table_name' => 'CLASS_NAME_WITH_NAMESPACE',
            'another_table_name' => 'CLASS_NAME_WITH_NAMESPACE',
        ];
    
        $className = $dictionary[$tableName];
        $models = null;
    
        if(class_exists($className)) {
            $models = $className::all();
        }
    
        // do some filtering, then return the model
        return $models;
    }
    

    【讨论】:

      【解决方案4】:

      我知道这是一个老问题,但它可以帮助某人:

      public function getModelFromTable($table)
      {
          foreach( get_declared_classes() as $class ) {
              if( is_subclass_of( $class, 'Illuminate\Database\Eloquent\Model' ) ) {
                  $model = new $class;
                  if ($model->getTable() === $table)
                      return $class;
              }
          }
      
          return false;
      }
      

      它会返回类名,所以你需要实例化它。

      【讨论】:

      • 不幸的是不包括模型。
      • 它确实支持模型,但是那些已经初始化的模型。简单的包含(使用)没有帮助,必须调用模型。
      【解决方案5】:

      替代变体。 我有我的基本模型 App\Models\Model 这个模型有静态方法getModelByTable,当然你可以把这个方法存放在你想要的任何地方。

      public static function getModelByTable($table)
          {
              if (!$table) return false;
              $model = false;
              switch ($table) {
                  case 'faq':
                      $model = Faq::class;
                      break;
                  case 'faq_items':
                      $model = FaqItems::class;
                      break;
              }
              if ($model) {
                  try {
                      $model = app()->make($model);
                  } catch (\Exception $e) {
      
                  }
              }
              return $model;
          }
      

      【讨论】:

        【解决方案6】:

        从以下继承,而不是从 Model。

        use Illuminate\Support\Str;
        
        class EnhancedModel extends \Illuminate\Database\Eloquent\Model
        {
            /**
             * The table associated with the model. Copies $table in Model
             *
             * @var string
             */
            protected static string $tableName;
        
            /**
             * Get the table associated with the model. Copies getTable() in Model
             *
             * @return string
             */
            public static function getTableName(): string
            {
                return static::$tableName ?? Str::snake(Str::pluralStudly(class_basename(static::class)));
            }
        
            /**
             * Get the table associated with the model. Overrides getTable() in Model
             *
             * @return string
             */
            public function getTable(): string
            {
                return $this::getTableName();
            }
        }
        

        要覆盖自动猜测的表名,请将其添加到您的 EnhancedModel 后代类中:

        protected static string $tableName = 'the_table_name';
        

        【讨论】:

          【解决方案7】:

          看起来 Laravel 6 做了一些改变。以下对我来说很好

          
              use Illuminate\Support\Str;
              ....
              $className = 'App\\' . Str::studly(str::singular($table_name));
                 if(class_exists($className)) {
                  $model = new $className; 
                 }
          
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-01-21
            • 2017-03-19
            • 2018-12-05
            • 1970-01-01
            • 1970-01-01
            • 2016-08-04
            • 2019-01-14
            • 2019-01-28
            相关资源
            最近更新 更多