I have following route group in my laravel 8.0 app:
Route::prefix('offline_transaction')->name('offline_transaction.')->group(function () {
Route::post('/approve/{transaction:uuid}', [OfflineTransactionController::class, 'approve'])
->name('approve');
Route::post('/reject/{transaction:uuid}', [OfflineTransactionController::class, 'reject'])
->name('reject');
});
And Transaction model is:
class Transaction extends Model implements CreditBlocker
{
//....
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AuthUserScope());
}
//....
}
And this is my AuthUserScope:
class AuthUserScope implements Scope
{
private string $fieldName;
public function __construct($fieldName = 'user_id')
{
$this->fieldName = $fieldName;
}
public function apply(Builder $builder, Model $model)
{
$user = Auth::user();
if ($user) {
$builder->where($this->fieldName, $user->id);
}
}
}
Now the problem is when an admin wants to approve or reject a transaction, 404 Not found error will throws. How can I pass this?
CodePudding user response:
Customizing The Resolution Logic
If you wish to define your own model binding resolution logic, you may use the
Route::bindmethod. The closure you pass to thebindmethod will receive the value of the URI segment and should return the instance of the class that should be injected into the route. Again, this customization should take place in thebootmethod of your application'sRouteServiceProvider:
Solution
What you can do is change the parameter name(s) in your routes/web.php file for the specific route(s).
Route::prefix('offline_transaction')->name('offline_transaction.')->group(function () {
Route::post('/approve/{any_transaction}', [OfflineTransactionController::class, 'approve'])
->name('approve');
Route::post('/reject/{any_transaction}', [OfflineTransactionController::class, 'reject'])
->name('reject');
Note the any_transaction. Change that to whatever naming convention you find most convenient.
Then, in your app/Providers/RouteServiceProvider.php file, change your boot(...) method to something like this:
use App\Models\Transaction;
use Illuminate\Support\Facades\Route;
// ...
public function boot()
{
// ...
Route::bind('any_transaction', function($uuid) {
return Transaction::withoutGlobalScopes()->where('uuid', $uuid)->firstOrFail();
});
// ...
}
// ...
Then in your controller app/Http/Controllers/OfflineTransactionController.php file, access the injected model:
use App\Models\Transaction;
// ...
public function approve(Transaction $any_transaction) {
// ...
}
// ...
Credits: Using Route Model Binding without Global Scope @thomaskim
Addendum
If you would like to remove a specific global scope from the route model bound query, you may use
withoutGlobalScope(AuthUserScope::class) in the boot(...) method of the app/Providers/RouteServiceProvider.php file.
