Fragster
@Fragster
помогло? отметь решением!

Как сделать так, чтобы применялся глобальный скоуп при байндинге роута (и выдавал ошибку)?

Появилась задача - сделать так, чтобы через определенные маршруты API не были доступны определенные элементы по критерию. Решил сделать с помощью применения глобального скоупа к моделям, написал middleware:

AddApiScopes.php

<?php

namespace App\Http\Middleware;

use App\Models\Order;
use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

class AddApiScopes
{
  /**
   * Handle an incoming request.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \Closure  $next
   * @return mixed
   */
  public function handle(Request $request, Closure $next)
  {
    Order::addGlobalScope('active', function (Builder $builder) {
      $builder->where('status', '<>', 0);
    });
    return $next($request);
  }
}



добавил его к группе маршрутов:
api.php

Route::prefix('/')->middleware(AddApiScopes::class)->group(function () {
//...
  Route::get('orders', [ApiController::class, 'orders']);
  Route::get('orders/{order}', [ApiController::class, 'order']);
//...
});



В методе 'orders' все работает, отображаются только элементы с нужными статусами
public function orders()
  {
    return OrderResource::collection(Order::all()); // тут скоуп применяется
  }


Однако в методе order, если в адресной строке вручную прописать id элемента с неправильным статусом - ошибка 404 не выдается, приходится дублировать код. Это грозит тем, что я забуду прописать этот код в каком-то месте, или могут быть косяки при изменении условий.
public function order(Order $order)
  {
    if ($order->status === 0) { // костыль
      abort(404);
    }
    return new OrderResource($order);
  }


Как сделать так, чтобы глобальный скоуп отрабатывал и для разрешения модели и я даже не попадал в эту процедуру?

Пока дошел до такого костыля:
Route::get('test/{order_id}', function ($order_id) { // выдает 404
    $order = Order::findOrFail($order_id);
    return $order;
  });
  Route::get('test2/{order}', function (Order $order) { // выдает данные модели
    return $order;
  });

но хочется, чтобы работал https://laravel.com/docs/8.x/routing#implicit-binding
  • Вопрос задан
  • 59 просмотров
Решения вопроса 1
Fragster
@Fragster Автор вопроса
помогло? отметь решением!
Нужно подставить мой middleware перед
\Illuminate\Routing\Middleware\SubstituteBindings::class
в приоритетах:
https://laravel.com/docs/8.x/middleware#sorting-mi...
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@Kostik_1993
Web Developer
Дерьмовое решение. Лучше мне кажется зарегестрировать парамер apiOrder или activeOrder и в сервис провайдере сделать нужный запрос

Например
Route::bind('activeOrder', function ($value) {
        return Order::active()->firstOrFail();
});
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы