#php #laravel #rest #http
Вопрос:
Я готовлю общий и текущий REST API типа CRUD с users
моделью, которую по умолчанию использует laravel
<?php
namespace AppModels;
use LaravelSanctumHasApiTokens;
use IlluminateNotificationsNotifiable;
use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateAuthPasswordsCanResetPassword;
class User extends Authenticatable implements MustVerifyEmail {
use HasApiTokens, HasFactory, Notifiable, CanResetPassword;
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = [
'name',
'email',
'password'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime'
];
}
и маршруты, которые я генерирую с помощью Route::apiResource
Route::apiResource('users', UserController);
Поскольку я хочу найти пользователя с помощью email
или id
я делаю ссылку или явное введение параметра маршрута RouteServiceProvider
внутри метода boot
с помощью Route::bind
Route::bind('user', function($userId){
$user = User::where(fn($query) => $query->where('id', $userId)->orWhere('email', $userId))->first();
if(request()->method() === 'PUT') return $user;
return $userId;
});
Это где главной темой приходит в этот метод ( Route::bind ()
) должен возвращать экземпляр класса, если нет, он вернется ExceptionModelNotFound 404 - not found
, но я хотел бы быть в состоянии появиться null
в мой контроллер и таким образом проверяют в зависимости от метода (или поставить патч), требуется ли создавать новую запись (которая согласно остальные принципы должны быть в состоянии сделать ресурс, если нет соответствия) или обновить существующую.
Мой update
метод UserController
заключается в следующем
public function update(Request $request, User $user){
$input = $request->all();
$method = $request->method();
if($method === 'PUT') $request->validate($this->rules);
$update = [
'PUT' => fn() => ($user) ? $user->update($input) : $user = $user::create($input),
'PATCH' => function() use($user, $input){
foreach ($input as $key => $val){
$user->$key = (!empty($val)) ? $val : $user->$key;
}
$user->save();
return $user;
}
];
return response()->json($update[$method]());
}
Раньше у меня это было без инъекции модели, и метод ùpdate
работал, что-то вроде этого
public function update(Request $request, $user){
Но из — за явной инъекции это больше не принимает параметр, кроме того, меня интересует только такое поведение при обновлении, так как это в остальных методах помогает сократить код, и это нормально для обработки 404-Не найдено.
Я не знаю, проваливаюсь ли я в чем-то или, может быть, laravel предлагает лучший способ сделать это, которого я не знаю.
Заранее спасибо.
PS: Код немного абстрагирован, он выглядит немного запутанным, потому что я попытался его упростить.
Ответ №1:
Вы не облегчаете себе задачу, создавая одно действие контроллера как для обновления, так и для создания пользователей. Я никогда не делал этого таким образом и всегда определяю ОСТАЛЬНЫЕ маршруты так:
PUT /user/1
= ОБНОВЛЕНИЕPOST /user
= СОЗДАТЬ
Вы должны знать на интерфейсе, создаете ли вы нового пользователя или обновляете существующего (например, просто проверьте наличие id
элемента).
Кроме того, привязка вашего текущего маршрута не является лучшей логикой, поскольку этот $user
запрос всегда выполняется, даже если он не является PUT
запросом. Тем не менее, этот код может быть значительно упрощен, если вы используете только firstOrFail()
этого пользователя, так как в любом случае вы должны разделить функциональность на 2 маршрута.
Лично я никогда не использую PATCH
, так как мои PUT
маршруты также допускают частичные обновления (например, только отправку email
обновления свойств).
Комментарии:
1. Спасибо, что ответили на Flame, ну, я попытался сделать это таким образом, потому что ОСТАЛЬНЫЕ принципы говорят, что с помощью метода ИСПРАВЛЕНИЯ выполняется частичное обновление, а с помощью метода PUT-полное обновление, и если строка, идентифицированная каким-либо уникальным столбцом, не существует, она создана. Что касается маршрутов, я создал их с помощью метода ApiResource, поэтому каждая операция обрабатывается своим методом, но я сомневался, почему laravel с ApiResource () предоставляет два маршрута (PUT и PATCH), которые указывают на контроллер метода обновления? это просто для того, чтобы выбрать предпочтительный метод ?.
2. А что касается привязки маршрута, я просто хотел проверить, существует ли она, вернуть строку, если нет, вернуть значение null, чтобы справиться с собой в контроллере.
3. Но все же спасибо, что ответили мне и рассказали о своем способе работы. Если нет возможности или это не принято на рабочем месте, я сделаю это проще.