在 laravel 12 中,要让只有管理员能编辑文章,给更新路由加上 auth 和 can:update,post,并让 postpolicy::update() 检查当前登录用户的 is_admin。以下示例适用于已有登录功能、post 模型、更新控制器和 users.is_admin 字段的项目。

PostPolicy 怎么判断当前用户是不是管理员
从当前认证用户读取 is_admin。在 User 模型现有的 casts() 中加入 is_admin 的 boolean 转换,这样策略里的 === true 可以正确处理数据库读出的布尔值。
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $user->is_admin === true;
}
}

配图是信息管理后台示意。按钮是否显示只影响界面。权限由后端策略决定,普通账号直接发出更新请求也要经过同一项检查。
把权限校验加到文章更新路由
将 PostPolicy 放在 app/Policies/PostPolicy.php。按 Laravel 默认命名约定,App\Models\Post 可自动发现对应策略。在 routes/web.php 导入控制器并为已有文章更新路由加上两个中间件。

use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
Route::put('/posts/{post}', [PostController::class, 'update'])
->middleware(['auth', 'can:update,post'])
->name('posts.update');
路由匹配到 /posts/{post} 后,Laravel 将当前用户和绑定的 Post 交给 PostPolicy::update()。策略拒绝时,响应应为 403,更新控制器不会执行。
控制器只写入允许编辑的字段
在已有的 PostController 中调整 update 方法。这里沿用前面的 auth 和 can 中间件。Post 模型与 Request 的 import 按项目已有文件补齐。示例假定 posts 表已有 title 和 body。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
public function update(\Illuminate\Http\Request $request, \App\Models\Post $post)
{
$data = $request->validate([
'title' => ['required', 'string', 'max:200'],
'body' => ['required', 'string'],
]);
$post->title = $data['title'];
$post->body = $data['body'];
$post->save();
return response()->noContent();
}在 User 模型已有的 casts() 返回值中合并 is_admin => boolean。通过后台或测试数据设定权限,用户资料更新接口只接收其允许修改的字段。
访客、普通用户和管理员会收到什么响应
用同一篇测试文章和同一份更新数据检查三个身份。未登录的 JSON 请求应收到 401,普通用户应收到 403,管理员在数据有效时应收到 204。再核对数据库,确认只有管理员的请求写入了新标题。
- 访客(未登录):访问文章列表正常,点击编辑链接应重定向至登录页或直接返回 401/403。
- 普通用户(is_admin=false):登录后可查看文章详情,但尝试 PUT/PATCH 更新接口时,应收到 403 错误,且数据库记录不变。
- 管理员(is_admin=true):拥有完整编辑权限,可提交表单更新标题、内容等字段,且 is_admin 字段不可被表单数据覆盖。
在 PostController::update 中只写入已验证的文章字段,例如 title 和 body。在用户资料更新接口中同样使用字段白名单,避免普通用户通过提交 is_admin 修改自己的权限。
用功能测试验证权限和文章是否写入
保存为 tests/Feature/UpdatePostAuthorizationTest.php。测试要求已有 users.is_admin 和 posts 的迁移、可用的 PostFactory,以及已注册的 posts.update 路由。使用独立测试数据库运行 php artisan test --filter=UpdatePostAuthorizationTest。
<?php
namespace Tests\Feature;
use App\Models\Post;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class UpdatePostAuthorizationTest extends TestCase
{
use RefreshDatabase;
public function test_only_admin_can_update_a_post(): void
{
$post = Post::factory()->create(['title' => 'Before']);
$reader = User::factory()->create(['is_admin' => false]);
$admin = User::factory()->create(['is_admin' => true]);
$url = route('posts.update', $post);
$payload = ['title' => 'After', 'body' => 'New content'];
$this->putJson($url, $payload)->assertUnauthorized();
$this->actingAs($reader)->putJson($url, $payload)->assertForbidden();
$this->assertSame('Before', $post->refresh()->title);
$this->actingAs($admin)->putJson($url, $payload)->assertNoContent();
$this->assertSame('After', $post->refresh()->title);
}
}示例使用 JSON 请求,因此访客应收到 401。普通网页请求可能按应用设置重定向至登录页。管理员通过验证后收到 204,数据库标题随之改变。

















