Laravel Model::firstOfCreate обработка ошибки
Здраствуйте. Только начал изучать Laravel и столкнулся с проблемой. В данном случае у меня есть модель User с уникальным полем, которую нужно записать в базу.Первый раз все срабатывает, а после возвращает ошибку SQL, что есть такой дубликат. Как мне правильно перехватить ошибку и допустим написать что такой Email уже существует? Для записи использую User::firstOrCreate.
Пример:
$user = User::firstOrCreate(
[
'email' => '[email protected]',
'name' => 'Mike',
'password' => Hash::make('123')
]);
Ответ Laravel
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '[email protected]' for key 'users_email_unique' (SQL: insert into `users` (`email`, `name`, `password`, `updated_at`, `created_at`) values ([email protected], Mike, $2y$10$yO3Sbjf.UVeOW9I0uSTHQ.xdzxxbBAYjYtYdxNS/zgwOPyKYbEPay, 2020-02-22 09:19:27, 2020-02-22 09:19:27))
Ответы (2 шт):
Поскольку Вы "только начали изучать Ларавел", позволю себе порекомендовать хорошую практику для решения этой, стандартной задачи: Нужно использовать валидацию форм ларавел, тут пример (https://github.com/woskresk/LA-simple-validation-form-request)
1) Создаём класс посредник: php artisan make:request StoreBlogPost и радектируем по примеру:
class StoreBlogPost extends FormRequest
{
public function authorize()
{
return true; //!!!ДЛЯ РАБОТЫ ВАЛИДАЦИИ УСТАНОВИТЬ ЗНАЧЕНИЕ "true"
}
public function rules()
{
return [
'email' => 'exists:states,abbreviation', // это правило проверки email на существование в базе данных
];
}
public function messages() // МЕТОД ДОБАВЛЯЕТСЯ ВРУЧНУЮ. ДЛЯ СОБСТВЕННЫХ ОПОВЕЩЕНИЙ ОБ ОШИБКАХ
{
return [
'email.exists' => 'Пользователь с данным email уже зарегистрирован', // добавляем текст ошибки
];
}
}
2) Меняем в исполняющем методе контроллера
public function store(Request $ request)
на
public function store(StoreBlogPost $ request)
3) Оформляем view для вывода ошибок
<input type="email" class="form-control @error('email') is-invalid @enderror" name="email">
@error('email')
<strong>{{ $message }}</strong>
@enderror
Все файлы из примера расположены (https://github.com/woskresk/LA-simple-validation-form-request). Если смог помочь поставьте лайк или подписку в github!)
Извините, если не актуально. В вашем случае вам нужно решить, нужны ли вам уникальные записи или нет. С помощью User::updateOrCreate вы можете обновить или создать запись.
Или
Пожалуйста, создайте запрос:
php artisan make:request YourRequest
Применить:
<?php
namespace App\Http\Requests;
use App\Rules\Password; // <- это твое правило
use App\Http\Requests\Request;
class YourRequest extends Request
{
/**
* Определите, авторизован ли пользователь для выполнения этого запроса.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Получите правила проверки, применимые к запросу.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
Вот пример того, как отображать ошибки для определенного поля: https://laravel.com/docs/10.x/validation#the-at-error-directive
php artisan make:rule Password
И вот правила:
<?php
namespace App\Rules;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Validation\ValidationException;
class Password implements Rule
{
/**
* Создать новый экземпляр правила.
*
* @return void
*/
protected $email
public function __construct(User $email)
{
$email = $this->email;
}
public function passes($attribute, $value)
{
$user = User::where('email', $this->email)->first();
try {
if($user === null) {
throw ValidationException::withMessages([
'email' => ['Электронная почта не верна.'],
]);
} else {
if (! Hash::check($value, $user['password'])) {
throw ValidationException::withMessages([
'password' => ['Неверный пароль.'],
]);
}
return true;
}
} catch (Exception $e) {
throw ValidationException::withMessages([
'password' => [$e->getMessage()],
]);
}
}
/**
* Получите сообщение об ошибке проверки.
*
* @return string
*/
public function message()
{
return 'Введенный пароль неверный.';
}
}
Не забудьте включить это правило в свой класс запроса:
app\Http\Requests\YourRequest.php
...
public static function rules()
{
return [
'email' => 'required|email|exists:users',
'password' => ['required', new Password()]
];
}
...
//////////////////////////
public function Signup(Request $request)
{
$user = User::where('email', $request->email)->first(); // правда или лож
$error = 'Этот пользователь уже зарегистрирован';
if(!$user) {
// create user
}
return back()->withErrors(['user' => $error ]); // else
}
///////////////////////////
$user = User::firstOrCreate(
['email' => $email], // твоя ошибка здесь
[
'email' => '[email protected]',
'name' => 'Mike',
'password' => Hash::make('123')
]
);
Показан этот ответ, потому что свойство находит первую запись или создает, если нет. Но вы не указали, по какому параметру искать совпадения. В моем примере это электронная почта.
Рад был помочь )
P.S. Sorry for the rough translation