Запрос PUT ресурса API Laravel 11. Нет результатов запроса для модели.Php

Кемеровские программисты php общаются здесь
Anonymous
Запрос PUT ресурса API Laravel 11. Нет результатов запроса для модели.

Сообщение Anonymous »

Я работаю над проектом API, использующим Laravel 11. Как уже упоминалось, когда я отправляю запрос PUT на определенные конечные точки, я получаю сообщение об ошибке:

"Нет результатов запроса для модели"

Ниже вы можете найти маршруты в коде api.php:

Код: Выделить всё

Route::prefix('area')->middleware('client')->group(function () {

Route::delete('country', [CountryController::class, 'destroyMultiple']);
Route::delete('city', [CityController::class, 'destroyMultiple']);
Route::delete('district', [DistrictController::class, 'destroyMultiple']);
Route::delete('neighborhood', [NeighborhoodController::class, 'destroyMultiple']);

Route::apiResource('country', CountryController::class);
Route::apiResource('city', CityController::class);
Route::apiResource('district', DistrictController::class);
Route::apiResource('neighborhood', NeighborhoodController::class);
});
Я получаю эту ошибку для каждого маршрута PUT, кроме маршрута CountryController PUT. Во-первых, это рабочая конечная точка в CountryController:

Код: Выделить всё

public function update(UpdateCountryRequest $request, Country $country)
{
DB::transaction(function () use ($request, $country) {
$country->update($request->only(['country_abbreviation', 'country_code', 'logo', 'status']));

$delete = [];

foreach ($request->languages as $language) {
$countryName = $country->CountryNames()->updateOrCreate([
'lang_id' => $language['lang_id'],
'country_id' => $country->id,
], $language);

$delete[] = $countryName->id;
}

CountryLanguage::where('country_id', $country->id)->whereNotIn('id', $delete)->delete();
});

return response()->json([
'message' => 'Country updated successfully',
'status' => 'success',
]);
}
А также файл UpdateCountryRequest, как показано ниже:

Код: Выделить всё

public function authorize(): bool
{
if ($this->user()->isAdmin) {
return true;
}

return false;
}

public function rules(): array
{
$country = $this->route('country');

return [
'country_abbreviation' => ['required', 'string', Rule::unique('countries')->ignore($country->id)], // keeping the same country_abbreviation seperately
'country_code' => ['required', 'string', 'max:5', Rule::unique('countries')->ignore($country->id)],
'logo' => ['required', 'string', 'max:255'],
'status' => ['required', 'boolean'],
'languages' => ['required', 'array'],
'languages.*.lang_id' => ['required', 'integer', 'exists:languages,id'],
'languages.*.country_name' => ['required', 'string'],
];
}
И запрос Postman PUT:
Изображение

Но для других контроллеров, когда я отправляю запрос PUT, я получаю упомянутую ошибку:

«Нет результатов запроса для модели»

Например, позвольте мне дать вам те же коды для DistrictController:
Обновить метот внутри файла контроллера:

Код: Выделить всё

 public function update(UpdateDistrictRequest $request, District $district)
{
DB::transaction(function () use ($request, $district) {
$district->update($request->validated());
});

return response()->json(['message' => 'District updated successfully'], 200);
}

Код: Выделить всё

UpdateDistrictRequest
код:

Код: Выделить всё

public function authorize(): bool
{
if ($this->user()->isAdmin) {
return true;
}

return false;
}

public function rules(): array
{
return [
'service_id' => 'required|integer',
'city_id' => 'required|integer|exists:cities,id',
'name' => 'required|string|max:255',
'status' => 'required|boolean',
];
}
А также PUT-запрос Postman:
[img]https://i.sstatic. net/ohDixxA4.png[/img]

Я проверил, существует ли район с данным идентификатором и существует ли он в базе данных.
Изображение

Ниже вы можете найти миграции:
Страна:

Код: Выделить всё

Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string('country_abbreviation');
$table->string('country_code');
$table->string('logo');
$table->tinyInteger('status');
$table->timestamps();
});
Район:

Код: Выделить всё

Schema::create('districts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('service_id')->nullable();
$table->unsignedBigInteger('city_id');
$table->foreign('city_id')->on('cities')->references('id')->onDelete('cascade');
$table->string('name');
$table->boolean('status')->default(1);
$table->timestamps();
});
А также модели:
Страна:

Код: Выделить всё

use HasFactory;

protected $guarded = [];

protected $fillable = [
'country_abbreviation',
'country_code',
'logo',
'status'
];

// ... Relationship methods
Район:

Код: Выделить всё

protected $guarded = [];

protected $fillable = [
'service_id',
'city_id',
'name',
'status'
];

// ... Relationship methods
Когда я запускаю метод «route:list» с помощью artisan, я вижу правильно перечисленные все конечные точки.
Я пробовал изменить определения маршрутов внутри api.php. Например, перемещение строки DistrictCotroller в начало, но она по-прежнему выдает ту же ошибку, в то же время, когда я делаю этот запрос CountryController, все еще работает правильно.
исключение выдается этим методом внутри src > Illuminate > Routing > ImlicitRouteBinding.php

Код: Выделить всё

public static function resolveForRoute($container, $route)
{
$parameters = $route->parameters();

$route = static::resolveBackedEnumsForRoute($route, $parameters);

foreach ($route->signatureParameters(['subClass' => UrlRoutable::class]) as $parameter) {

if (!$parameterName = static::getParameterName($parameter->getName(), $parameters)) {
continue;
}

$parameterValue = $parameters[$parameterName];

if ($parameterValue instanceof UrlRoutable) {
continue;
}

$instance = $container->make(Reflector::getParameterClassName($parameter));

$parent = $route->parentOfParameter($parameterName);

$routeBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance))
? 'resolveSoftDeletableRouteBinding'
: 'resolveRouteBinding';

if (
$parent instanceof UrlRoutable &&
!$route->preventsScopedBindings() &&
($route->enforcesScopedBindings() || array_key_exists($parameterName, $route->bindingFields()))
) {
$childRouteBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance))
? 'resolveSoftDeletableChildRouteBinding'
: 'resolveChildRouteBinding';

if (
!$model = $parent->{$childRouteBindingMethod}(
$parameterName,
$parameterValue,
$route->bindingFieldFor($parameterName)
)
) {
throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
}
} elseif (!$model = $instance->{$routeBindingMethod}($parameterValue, $route->bindingFieldFor($parameterName))) {
// EXCEPTION
throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
}

$route->setParameter($parameterName, $model);
}
}
Я изменил методы обновления как в CountryController, так и в DistrictController, как показано ниже, и заметил, что в DistrictController запрос к базе данных просто не работает.

Код: Выделить всё

// CountryController update
public function update(UpdateCountryRequest $request, int $id)
{
dd($id, District::find($id)); // 1, District {#1444 ...}

// DistrictController update
public function update(UpdateDistrictRequest $request, int $id)
{
dd($id, District::find($id)); // 1, null
Я дважды проверил пространства имен в обоих контроллерах, и они идентичны.
[img]https: //i.sstatic.net/pzH8uePf.png[/img]

Похоже, проблема вызвана глобальными областями, которые я пропустил. В наших моделях у нас есть функции загрузки, как показано ниже, для регистрации глобальных областей в сервисном контейнере, я полагаю:

Код: Выделить всё

// District Model
protected static function boot()
{
parent::boot();

static::addGlobalScope(new FilterBy('App\Services\V1\Area\DistrictFilters', request()->all()));
}
Также ниже вы можете найти коды файлов области действия FilterBy:

Код: Выделить всё

class FilterBy implements Scope
{
protected $namespace;
protected $filters;

public function __construct($namespace, $filters)
{
$this->namespace = $namespace;
$this->filters = $filters;
}
/**
* Apply the scope to a given Eloquent query builder.
*/
public function apply(Builder $builder, Model $model): void
{
$filter = new FilterBuilder($builder, $this->filters, $this->namespace);
$builder = $filter->apply();
}
}
А также в классе FilterBuilder мы применяем фильтры, как показано ниже:

Код: Выделить всё

public function apply()
{
foreach ($this->filters as $name => $value) {
$normailizedName = ucfirst($name);
$class = $this->namespace .  "\\{$normailizedName}";

if (! class_exists($class)) {
continue;
}

if (strlen($value)) {
(new $class($this->query))->handle($value);
} else {
(new $class($this->query))->handle();
}
}

return $this->query;
}
И, наконец, у нас есть файлы Name.php и CityId.php внутри заданного пространства имен App\Services\V1\Area\DistrictFilters. Внутри них есть методы handle, как показано ниже:

Код: Выделить всё

public function handle($value = ""): void
{
// Name.php
$this->query->where('name', 'ilike','%'. $value .'%');
}
Итак, если я правильно понимаю, когда я отправляю запрос PUT, скажем, к DistrictController, например, из-за этих QueryFilters, если я не отправлю '', поскольку оно сохранено в базе данных, оно просто не может найти модель.
Например, я создал запись Distrcit, которая имеет идентификатор с 974 как ниже:
Изображение

Если я отправлю запрос PUT, как показано ниже, с тем же '', ему удается найти Модель и обновить ее:

Код: Выделить всё

{
"service_id" : 1,
"city_id" : 1,
"name" : "District",
"status" : 1
}
Но если я отправлю тот же запрос с обновленным именем, что-то вроде '

Код: Выделить всё

District 123
' он не может найти модель.
Поэтому я обновил функцию Apply внутри FilterBy, как показано ниже, чтобы предотвратить добавление QueryFilters и кажется, это решило проблему:

Код: Выделить всё

public function apply(Builder $builder, Model $model): void
{
if (collect(['PUT', 'PATCH'])->contains(request()->method())) {
return;
}

$filter = new FilterBuilder($builder, $this->filters, $this->namespace);
$builder = $filter->apply();
}
Было бы быстрее найти проблему, если бы я поделился кодом модели всего округа. Это моя вина. Спасибо всем за попытку помочь.

Подробнее здесь: https://stackoverflow.com/questions/784 ... -for-model

Вернуться в «Php»