将应用程序部署到生产环境后,你可能偶尔需要「模拟」应用程序的另一个用户,以调试客户报告的问题。值得庆幸的是,Nova 包含处理这种情况的内置功能。
要启用模拟用户功能,请在应用程序的 User 模型中添加 Laravel\Nova\Auth\Impersonatable 特性:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Nova\Auth\Impersonatable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Impersonatable, Notifiable;
// ...
}一旦将 Impersonatable 特性添加到应用程序的 User 模型中,「模拟用户」操作将可通过相应资源的内联操作菜单使用:

默认情况下,任何有权限查看 Nova 面板的用户都可以模拟任何其他用户。不过,你可以通过在应用程序的 Impersonatable 模型上定义 canImpersonate 和 canBeImpersonated 方法,自定义谁可以模拟其他用户以及哪些用户可以被模拟:
use Illuminate\Support\Facades\Gate;
/**
* 确定用户是否可以模拟其他用户。
*
* @return bool
*/
public function canImpersonate()
{
return Gate::forUser($this)->check('viewNova');
}
/**
* 确定用户是否可以被模拟。
*
* @return bool
*/
public function canBeImpersonated()
{
return true;
}通过 Laravel 的服务容器解析 Laravel/Nova\Contracts\ImpersonatesUsers 接口的实现,就可以检查应用程序当前的模拟状态:
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Laravel\Nova\Contracts\ImpersonatesUsers;
Route::get('/impersonation', function (Request $request, ImpersonatesUsers $impersonator) {
if ($impersonator->impersonating($request)) {
$impersonator->stopImpersonating($request, Auth::guard(), User::class);
}
});默认情况下,你可以通过使用模拟的可用事件来添加额外的自定义功能:
Laravel\Nova\Events\StartedImpersonatingLaravel\Nova\Events\StoppedImpersonating例如,你可能希望记录模拟事件,你可以在应用程序的 EventServiceProvider 的 boot 方法中为这些事件注册监听器:
use Illuminate\Support\Facades\Event;
use Laravel\Nova\Events\StartedImpersonating;
use Laravel\Nova\Events\StoppedImpersonating;
Event::listen(StartedImpersonating::class, function ($event) {
logger("User {$event->impersonator->name} started impersonating {$event->impersonated->name}");
});
Event::listen(StoppedImpersonating::class, function ($event) {
logger("User {$event->impersonator->name} stopped impersonating {$event->impersonated->name}");
});