我的 laravel 8.0 应用程序中有以下路线组:
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');
});
并且
Transaction
型号是:
class Transaction extends Model implements CreditBlocker
{
//....
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AuthUserScope());
}
//....
}
这是我的
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);
}
}
}
transaction
时,将会抛出 404 Not found 错误。我怎样才能通过这个?如果您想定义自己的模型绑定解析逻辑,您可以 使用
方法。您传递给Route::bind
的闭包 方法将接收 URI 段的值并应返回 应注入到路由中的类的实例。再次, 此定制应该在您的bind
方法中进行 应用程序的boot
:RouteServiceProvider
您可以做的是更改特定路线的
routes/web.php
文件中的参数名称。
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');
注意
any_transaction
。将其更改为您认为最方便的任何命名约定。
然后,在您的
app/Providers/RouteServiceProvider.php
文件中,将您的 boot(...)
方法更改为如下所示:
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();
});
// ...
}
// ...
然后在控制器
app/Http/Controllers/OfflineTransactionController.php
文件中,访问注入的模型:
use App\Models\Transaction;
// ...
public function approve(Transaction $any_transaction) {
// ...
}
// ...
鸣谢:在没有全局作用域的情况下使用路由模型绑定@thomaskim
如果您想从路由模型绑定查询中删除特定的全局范围,您可以使用
withoutGlobalScope(AuthUserScope::class)
在 boot(...)
文件的 app/Providers/RouteServiceProvider.php
方法中。
另一种方法是我可以在
Route::currentRouteNamed
类中使用 AuthUserScope
,如下所示,我更喜欢使用它而不是 Route::bind
:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
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 && !Route::currentRouteNamed('admin.*')) {
$builder->where($this->fieldName, $user->id);
}
}
}
我们也可以这样做。
/**
* Retrieve the model for a bound value.
*
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->withoutGlobalScopes()->where($field ?? $this->getRouteKeyName(), $value)->first();
}
在上面的代码中,我们实际上重写了模型文件中现有的方法,该方法在 Laravel 中的每个模型类中扩展。
只需在现有查询中添加
withoutGlobalScopes
即可正常工作。
在我的具体情况下,我想删除全局作用域,同时仍然保留子关系的隐式作用域。
我通过以下方式实现了这一点
routes/web.php
Route::get('/parents/{parent}/children/{child:id}/'[
\App\Http\Controllers\ChildrenController::class, 'show'])
->name('showAllChildren');
模型/Child.php
use Illuminate\Support\Facades\Route;
public function resolveRouteBindingQuery($query, $value, $field = null)
{
if(Route::currentRouteNamed('showAllChildren')){
return $query->withoutGlobalScope()->where($field ?? $this->getRouteKeyName(), $value);
}
return parent::resolveRouteBindingQuery($query, $value, $field);
}
这允许我忽略此路由上的全局应用范围,同时仍然使用具有自定义键范围的隐式路由模型绑定。