tldr:
Как вы динамически получаете экземпляр модели только по имени таблицы БД?
Что вы получите по запросу:
- 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;
}