如何用Viewi构建登录守卫:组件级中间件完整指南
【免费下载链接】viewiUnique and efficient front-end framework for PHP项目地址: https://gitcode.com/gh_mirrors/vi/viewi
Viewi 是一款独特的 PHP 前端框架(Unique and efficient front-end framework for PHP)。它内置的组件级中间件(Middleware)机制,让你只需一个类、一行属性,就能为任意页面组件添加登录守卫(Login Guard),在组件渲染前拦截未登录用户,无需手写任何路由判断逻辑。
为什么需要登录守卫 🔐
传统做法是在每个受保护页面里手动判断"用户是否登录",代码重复且容易遗漏。Viewi 把守卫做成组件属性:
- ✅ 声明式:在组件类上一行声明,无需侵入页面逻辑
- ✅ 组件级生效:守卫只对绑定的组件起作用,粒度比全站中间件更细
- ✅ 可组合:一个组件可挂多个守卫,按顺序执行
客户端渲染入口 renderApp.ts 会在组件渲染前先跑完整个守卫链,任何一个守卫拒绝(next(false)),组件就不会被渲染。
3步搭建登录守卫
第1步:安装 Viewi
git clone https://gitcode.com/gh_mirrors/vi/viewi第2步:编写守卫类
守卫只需实现 IMIddleware 接口,在run()方法中调用next()决定是否放行:
use Viewi\Components\Middleware\IMIddleware; use Viewi\Components\Middleware\IMIddlewareContext; use Viewi\Components\Browser\BrowserSession; use Viewi\Components\Routing\ClientRoute; class AuthGuard implements IMIddleware { public function __construct( private BrowserSession $session, private ClientRoute $route ) {} public function run(IMIddlewareContext $c) { $user = $this->session->getItem('user'); if ($user === null) { $this->route->navigate('/login'); // 跳转登录页 $c->next(false); // 拦截 return; } $c->next(true); // 放行 } }💡 小技巧:Viewi 的 BrowserSession 可读写浏览器 sessionStorage,ClientRoute 负责页面跳转,两者可直接注入守卫构造函数。
第3步:把守卫绑定到组件
使用 Middleware 属性 声明式绑定,一行搞定:
use Viewi\Components\Attributes\Middleware; #[Middleware([AuthGuard::class])] class DashboardPage extends BaseComponent { // 未登录时,这个页面根本不会渲染 }构建时,Builder 会自动解析Middleware属性,把守卫清单写入组件元数据,并在客户端渲染前按序执行——整个过程零配置。
带参数的守卫:一份代码,多处复用 🔁
守卫支持参数化绑定:在类名后追加位置参数,Viewi 会自动按构造函数参数名注入。
class RoleGuard implements IMIddleware { public function __construct(public string $role) {} public function run(IMIddlewareContext $c) { // 只允许 $role 角色访问 $c->next(checkRole($this->role)); } } #[Middleware([[RoleGuard::class, 'admin']])] class AdminPage extends BaseComponent {} #[Middleware([AuthGuard::class, [RoleGuard::class, 'editor']])] class EditPage extends BaseComponent {}注意两点:
| 写法 | 含义 |
|---|---|
'Class::class'字符串 | 无参数守卫 |
['Class::class', 参数1, ...]数组 | 带参数守卫,参数按构造函数形名注入 |
一个组件可以同时挂多个守卫,从左到右依次执行,任一项拦截即终止。
登录守卫最佳实践清单
- 🎯只拦截、少渲染:
next(false)后客户端会直接停止渲染,配合navigate()跳转登录页体验最佳 - 🔁复用守卫:用参数化守卫(如 RoleGuard)避免为每种权限写一个新类
- 🧪登录页保持无守卫:给登录页加
AuthGuard会造成跳转死循环 - ⚡守卫内保持轻量:守卫在每次组件渲染前执行,避免在其中做耗时 IO
常见问题排查 🛠️
Q:守卫不生效,页面还是渲染了?检查Middleware属性是否写在组件类上(它只支持Attribute::TARGET_CLASS),且守卫类已实现IMIddleware接口。
Q:拦截后页面空白,没有跳转?确保在next(false)之前调用了$route->navigate('/login'),或自行处理重定向。
Q:多个守卫的执行顺序?按#[Middleware([...])]数组中的声明顺序依次执行,全部next(true)才会渲染组件(见 renderApp.ts 中的守卫链实现)。
核心源码路径速查
| 文件 | 作用 |
|---|---|
| Middleware.php | 组件级守卫声明属性 |
| IMIddleware.php | 守卫接口定义 |
| IMIddlewareContext.php | next(bool)放行/拦截上下文 |
| Builder.php | 构建期解析守卫清单 |
| routes.php | 路由注册示例(可放登录页路由) |
掌握这套机制后,登录守卫、角色权限、功能开关等场景都可以用同一个模式优雅解决——这正是 Viewi "高效"理念的体现。
【免费下载链接】viewiUnique and efficient front-end framework for PHP项目地址: https://gitcode.com/gh_mirrors/vi/viewi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考