如何仅通过数据库表名称动态获取模型的实例?
您从请求中获得的信息:
您不知道的地方:
我有一个报告系统,用户可以用来报告某些东西。对于每个报告,都会发送ID和表名。
直到现在,每个模型都位于命名空间App\*
下。但是,由于我的项目太大,我需要将一些代码分成Modules\*
这是一个示例,该报告如何保存在数据库中:
示例:
请求包含规则:
public function rules()
{
return [
'id' => 'required|string',
'type' => 'required|in:users,comments,offer_reviews, ......',
'reason' => 'required|string',
'meta' => 'nullable|array',
'meta.*' => 'string|max:300'
];
}
在数据库中,我们将数据保存到:
id reportable_type ...
1 App\User ...
4 Modules\Review\OfferReview ...
当您仅知道数据库表名称(例如offer_reviews
)时,如何动态创建模型的实例?
我想到了一个解决方案,但是,我不确定它是否增加了更多的安全性问题。如果用户发送完整的名称空间+类名该怎么办?这样,我就直接知道在哪里解析实例。
//在我的控制器中
class ReportController extends Controller
{
/**
* Stores the report in DB.
*/
public function store(StoreReportRequest $request)
{
$model = $request->getModel();
$model->report([
'reason' => $request->reason,
'meta' => $request->meta
], auth()->user());
return response()->json(['status' => 'Submitted'], 201);
}
}
//在StoreReportRequest中
/**
* Gets the Model dynamically.
* If not found we throw an error
* @return \App\Model
*/
public function getModel()
{
return get_model($this->type)
->findOrFail(\Hashids::decode($this->id)[0]);
}
//在助手中
/**
* Gets me the model of a table name.
* @param String $table Has to be the name of a table of Database
* @return Eloquent The model itself
*/
function get_model($table)
{
if (Schema::hasTable(strtolower($table))) {
return resolve('App\\' . Str::studly(Str::singular($table)));
}
throw new TableNotFound;
}
答案 0 :(得分:0)
我不知道是否有更好的解决方案,但是您可以。当找不到我们使用App\
作为命名空间的代码时,我的代码正在寻找带有命名空间的方法。
也许这段代码可以帮助某人:)
class StoreReportRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'id' => 'required|string',
'type' => 'required|in:mc_messages,profile_tweets,food,users,comments,offer_reviews,user_reviews',
'reason' => 'required|string',
'meta' => 'nullable|array',
'meta.*' => 'string|max:300'
];
}
/**
* Gets the Model dynamically.
* If not found we throw an error
* @return \App\Model
*/
public function getModel()
{
$namespace = $this->getNamespace();
return $this->resolveModel($namespace);
}
protected function getNamespace(): string
{
$method = $this->typeToMethod();
if (method_exists($this, $method)) {
return $this->$method();
}
return 'App\\';
}
protected function typeToMethod(): string
{
return 'get' . \Str::studly(\Str::singular($this->type)) . 'Namespace';
}
protected function resolveModel(string $namespace)
{
return get_model($this->type, $namespace)
->findOrFail(\Hashids::decode($this->id)[0]);
}
protected function getOfferReviewNamespace(): string
{
return 'Modules\Review\Entities\\';
}
protected function getUserReviewNamespace(): string
{
return 'Modules\Review\Entities\\';
}
}