Вызов модели Laravel по строке

Можно ли назвать модель Laravel строкой?

Это то, чего я пытаюсь достичь, но его провал:

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

Я получаю следующее исключение:

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

Ответ 1

Да, вы можете это сделать, но вам нужно использовать полное имя класса:

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

Если ваше имя модели хранится в чем-то отличном от простой переменной (например, атрибуте объекта), вам нужно будет использовать промежуточную переменную, чтобы заставить ее работать.

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

Ответ 2

Попробуйте следующее:

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

Ответ 3

Да, вы можете сделать это более гибким способом. Создать общую функцию.

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

Кстати я люблю использовать такие функции.

Ответ 4

если вы используете его во многих местах, используйте эту функцию

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();

Надеюсь, поможет

Ответ 5

Этот метод должен хорошо работать:

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()