全局共享数据必须在AppServiceProvider::boot()中调用view()->share(),因其是静态绑定、非每次渲染执行;控制器或中间件中调用不可靠,register()中则因View未初始化而报错。

全局共享数据必须在 AppServiceProvider::boot() 里调用 view()->share(),其他位置要么无效、要么不可靠。
为什么不能在控制器或中间件里调用 view()->share()
它不是“每次渲染都执行一次”的逻辑,而是“注册一次、全局生效”的静态绑定。写在 BaseController 构造函数里,只对继承它的控制器生效;写在中间件里,可能因中间件执行顺序靠后,导致部分视图(比如邮件模板、PDF 渲染)根本没被注入——因为视图已经提前渲染完了。
-
AppServiceProvider::register()更不行:这时View门面还没初始化,会直接报Call to a member function share() on null - 如果只希望某些页面有数据,比如后台管理页,
view()->share()就不合适——它真·全局,连resources/views/vendor/mail/html/message.blade.php都会被塞进去 - 传对象要小心:
view()->share('user', auth()->user())可以,但view()->share('request', request())会触发序列化错误或副作用
view()->composer() 适合什么场景
当你需要“按需查库”“带权限判断”“依赖当前路由或请求上下文”时,view()->composer() 才是正解。它在视图渲染前才执行回调,天然支持动态逻辑。
- 第一个参数支持通配符:
'admin.*'匹配所有 admin 目录下的视图,'*'表示全部——但别轻易用*,查一次用户信息就跑一遍,性能扛不住 - 可以用闭包,也可以用类:
view()->composer('navigation', function ($view) { $view->with('nav_items', Nav::active()->get()); }) - 类方式更易维护:
App\Http\ViewComposers\NavComposer里写compose()方法,里面能用 DI、能查缓存、能做 if 判断
变量在 Blade 里怎么安全判断是否存在
isset($site_name) 不可靠——view()->share() 注入的是视图上下文数据,不是 PHP 全局变量,可能被后续 with() 覆盖或 unset 掉。
- 最稳妥的是用空合并:
{{ $site_name ?? '默认值' }} - 调试时加
{{ dd(get_defined_vars()) }},一眼看清哪些变量真正在作用域里 - 组件里能用共享变量,但不能自动透传进
<x-header :title="$site_name"></x-header>的属性链——那是 props 机制,和view()->share()无关
真正容易被忽略的点是:共享数据一旦注册,就对所有视图生效,包括你没意识到的地方(比如队列任务里渲染的邮件、Artisan 命令生成的 PDF)。轻量、高频、不变的数据才适合 view()->share();带状态、需上下文、查库耗时的,一律走 view()->composer()。


















