通过字符串调用Laravel模型

31

能否通过字符串调用Laravel模型?

这就是我想要实现的,但却失败了:

$model_name = 'User';
$model_name::where('id', $id)->first();

我遇到了以下异常:

exception 'ErrorException' with message 'Undefined variable: User'

2
尝试使用完整的命名空间,例如$model_name = 'App\Http\Model\User'; - Cerlin
那个方法可行,但我实际上是想从一个实例变量中执行它,但仍然失败了:${$this->model_name}::where - Parampal Pooni
请问您能描述一下您的评论吗? - Kalhan.Toress
1
当然,也可以使用app($model_name)->where(...) - Yoram de Langen
6个回答

74

是的,你可以这样做,但需要使用完全限定的类名:

$model_name = 'App\Model\User';
$model_name::where('id', $id)->first();

如果您的模型名称存储在除普通变量(例如对象属性)以外的其他地方,您需要使用中间变量才能使其正常工作。

$model = $this->model_name;
$model::where('id', $id)->first();

30

试一试:

$model_name = 'User';
$model = app("App\Model\{$model_name}");
$model->where('id', $id)->first();

5
你为什么使用了app()?谢谢。 - Raja Khoury
1
尝试使用@RajaKhoury获取实例,或者换句话说,“返回var_dump(app('App \ User'));”并查看结果。 - Vit
1
我不得不用另一个反斜杠来转义尾部的反斜杠:$modelPath = "App\Models\\{$modelName}"; - Luke
这正是我所需要的,下一次你只需要提供一个详细的描述,说明你的代码预期要做什么,因为我们有些人在开始打字之前会在脑海中运行代码。 - 3m1n3nc3

2

这种方法应该很有效:

最初的回答

private function getNamespace($model){
    $dirs = glob('../app/Models/*/*');

    return array_map(function ($dir) use ($model) {
        if (strpos($dir, $model)) {
            return ucfirst(str_replace(
                '/',
                '\\',
                str_replace(['../', '.php'], '', $dir)
            ));
        }
    }, array_filter($dirs, function ($dir) use ($model) {
        return strpos($dir, $model);
    }));
}

我的项目有多个子目录,这个函数可以很好地工作。因此,我使用$model = current($this->getNamespace($this->request->get('model'))); 恢复模型的命名空间,然后只需调用我的查询:$model::all()。"最初的回答"

1
如果你在很多地方都要使用它,就使用这个函数。
function convertVariableToModelName($modelName='',$nameSpace='App')
        {
            if (empty($nameSpace) || is_null($nameSpace) || $nameSpace === "") 
            {                
               $modelNameWithNameSpace = "App".'\\'.$modelName;
                return app($modelNameWithNameSpace);    
            }

            if (is_array($nameSpace)) 
            {
                $nameSpace = implode('\\', $nameSpace);
                $modelNameWithNameSpace = $nameSpace.'\\'.$modelName;
                return app($modelNameWithNameSpace);    
            }elseif (!is_array($nameSpace)) 
            {
                $modelNameWithNameSpace = $nameSpace.'\\'.$modelName;
                return app($modelNameWithNameSpace);    
            }
        }

例如,如果您想获取所有用户

情景1:

 $userModel= convertVariableToModelName('User');
  $result = $userModel::all();

情境2:

如果您的模型在自定义命名空间中,可能是App\Models

$userModel= convertVariableToModelName('User',['App','Models']);
$result = $userModel::all();

希望能有所帮助


0

是的,你可以用更灵活的方式来实现。创建一个通用函数。

function getWhere($yourModel, $select, $is_model_full_path=null, $condition_arr=null)
{
    if(!$is_model_full_path){ // if your model exist in App directory
        $yourModel ="App\\$yourModel";
    }
    if(!$condition_arr){
        return $yourModel::all($select)->toArray();
    }
    return $App_models_yourModel::all($select)->where($condition_arr)->toArray();
}

现在你可以以不同的方式调用这个方法。

getWhere('User', ['id', 'name']); // with default path of model
getWhere('App\Models\User', ['id', 'name'], true); // with custom path of model
getWhere('User', ['id', 'name'], false, ['id', 1]); // with condition array

顺便说一下,我喜欢使用这样的函数。


0

你也可以尝试这样做:

use App\Model\User;

class UsersController extends Controller
{

 protected $model;

 public function __construct(User $model)
 {
    $this->model = $model;
 }

 public function getUser()
 {
  $data = $this->model->where('id', $id)->first();

  return $data;
 }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接