Существует несколько способов решения этой проблемы. Я предложу здесь три решения, но имейте в виду, что вы можете выбрать одно из трех, какую-то комбинацию из трех или что-то совершенно другое.
Метод 1:Фронтенд
Лично я считаю, что это лучшее решение. Его проще всего реализовать, и он дает желаемый результат. Все, что вам нужно сделать, это отключить кнопку «Добавить», если Training
уже имеет Observation
записано:
your-view.blade.php:
<h1>Listing Observations</h1>
<!-- Observations Table -->
<button{{ $training->observations()->exists() ? ' disabled' : '' }}>Add</button>
Этого будет достаточно для 99,999% всех пользователей этого приложения. Конечно, опытный пользователь все еще может отправить запрос, несмотря на то, что кнопка отключена. По моему (циничному) мнению, я не собираюсь «элегантно проваливаться» для пользователя, который пытается обойти систему.
Но это зависит от вас. Вы можете просто реализовать этот метод и назвать его хорошим. Если вы решили, что хотите, чтобы система была более устойчивой, вы можете реализовать метод 2 или метод 3.
ПРИМЕЧАНИЕ : По моему мнению, если вы решите реализовать метод 2или 3, , вы все равно должны реализовать метод 1 . Его очень просто реализовать, и он обеспечивает гораздо более приятный UX, чем позволить пользователю заполнить форму Observation
, а затем сказать им, что ему разрешено создать только один Observation
.
.
Метод 2: Backend - Eloquent
Eloquent позволяет запросить наличие связанной модели. Это означает, что вы можете проверить, есть ли у Training
соответствующий Observation
, прежде чем создавать его.
public function store(Request $request)
{
$request->validate([
'instruction' => 'required',
'description' => 'required',
'fk_student' => 'required'
]);
$instruction = $request->get('instruction');
$description = $request->get('description');
$fk_student = $request->get('fk_student');
$trainings = Training::where('fk_student', $request->get('fk_student'))->first();
if(!isset($trainings)){
return redirect()->route('observations.index')
->with('error', 'No training, no observation! ');
}
if ($trainings->observations()->exists()) {
/******************************************************************************
* I'm returning a plain text response. Depending on your front end code, it
* might make more sense to return a JSON response. Whatever response type you
* choose, make sure that you respond with an HTTP error code. I think
* 400 – Bad Request makes the most sense).
******************************************************************************
*/
return response('An Observation already exists for this Training', 400)
->header('Content-Type', 'text/plain');
}
// If we make it to this point, it is safe to go ahead and create the Observation
Observation::create($request->all());
return redirect()->route('observations.index')
->with('success', 'Add');
}
Метод 3: Серверная часть - База данных
Наконец, вы можете позволить базе данных обработать это для вас. Идея этого метода заключается в том, что вы создаете ограничение базы данных, ограничивающее число Observations
на Training
одним. Имея это ограничение, вы обрабатываете отправку формы с предположением, что все идеально.
Однако, поскольку все не будет всегда идеально, вы должны окружить свой код блоком try/catch
и обработать исключение, что база данных будетthrow.
/****************************************************************
* You can add this to a new or an existing database migration.
****************************************************************
*/
public function up()
{
Schema::table('observations', function($table) {
$table->unsignedInteger('training_id')
->unique()
->nullable();
});
}
YourController.php
public function store(Request $request)
{
$request->validate([
'instruction' => 'required',
'description' => 'required',
'fk_student' => 'required'
]);
$instruction = $request->get('instruction');
$description = $request->get('description');
$fk_student = $request->get('fk_student');
$trainings = Training::where('fk_student', $request->get('fk_student'))->first();
if(!isset($trainings)){
return redirect()->route('observations.index')
->with('error', 'No training, no observation! ');
}
try {
Observation::create($request->all());
return redirect()->route('observations.index')
->with('success', 'Add');
} catch (\Exception $e) {
/******************************************************************************
* You shouldn't *really* return `$e->getMessage()` to the user. Just return
* an error message that makes sense for the action the user attempted.
******************************************************************************
*/
return response($e->getMessage(), 400)->header('Content-Type', 'text/plain');
}
}