Laravel8如何像LoginController一样无需手动调用即可使用Trait方法
问题描述
- 参照网络教程编写的自定义Trait可正常运行,但使用时必须手动调用Trait内的方法才能生效
- Laravel框架自带的
LoginController仅需引入AuthenticatesUsersTrait,控制器内无需额外编写showLoginForm()、login()等方法,登录相关功能即可正常使用,这些方法实际定义在AuthenticatesUsersTrait中,示例代码如下:
use Illuminate\Foundation\Auth\AuthenticatesUsers; class LoginController extends Controller { use AuthenticatesUsers; }
- 自行编写的Trait必须手动调用内部方法才可使用,相关代码如下:
- 文件路径:
app\Traits\MenuTrait.php
<?php namespace App\Traits; use Illuminate\Http\Request; trait MenuTrait { public function getMenus() { $menus[] = [ 'id' => 'menu-dashboard', 'icon' => 'fas fa-home', 'name' => 'Dashboard', 'href' => route('lang.admin.dashboard'), 'children' => [] ]; // 其余业务代码省略
- 文件路径:
app\Http\Controllers\Admin\DashboardController.php
// 其余引用代码省略 use App\Traits\MenuTrait; class DashboardController extends Controller { use MenuTrait; public function index() { $data['menus'] = $this->getMenus(); return view('ocadmin.dashboard', $data); } // 其余业务代码省略
核心疑问:如何实现自定义Trait的方法无需手动调用即可自动生效?
解答
首先纠正一个认知偏差:AuthenticatesUsers中的方法并不是引入后就自动执行,它的生效逻辑是路由将对应请求直接映射到了Trait内的同名方法——比如路由配置中GET /login指向LoginController@showLoginForm,控制器本身没有定义该方法时,PHP会自动调用Trait内的showLoginForm实现,不存在「不触发就自动运行」的特殊逻辑。
如果要实现引入MenuTrait后不需要在每个控制器方法中手动调用getMenus(),自动将菜单数据注入视图,可以通过以下方式实现:
方案1:利用控制器Trait初始化钩子自动执行
Laravel控制器原生支持Trait初始化方法:在Trait中定义initialize[TraitName]格式的方法,控制器实例化时会自动执行该方法,不需要手动调用。
修改MenuTrait代码如下:
<?php namespace App\Traits; use Illuminate\Http\Request; trait MenuTrait { // 控制器初始化时自动执行,方法名必须和Trait名对应 public function initializeMenuTrait() { // 直接将菜单数据共享到视图,无需控制器手动传参 view()->share('menus', $this->getMenus()); } public function getMenus() { $menus[] = [ 'id' => 'menu-dashboard', 'icon' => 'fas fa-home', 'name' => 'Dashboard', 'href' => route('lang.admin.dashboard'), 'children' => [] ]; // 其余业务代码省略 return $menus; } }
修改后控制器代码可以简化为:
// 其余引用代码省略 use App\Traits\MenuTrait; class DashboardController extends Controller { use MenuTrait; public function index() { return view('ocadmin.dashboard'); } // 其余业务代码省略 }
只要控制器引入了MenuTrait,对应视图中就可以直接使用$menus变量,不需要手动调用方法传参。
方案2:全局视图共享(适合全页面通用菜单场景)
如果菜单是后台所有页面都需要加载的公共数据,不需要给每个控制器加Trait,可以直接在app/Providers/AppServiceProvider.php的boot方法中做视图共享,所有渲染的视图都会自动注入菜单数据,连引入Trait的步骤都可以省略。
内容的提问来源于stack exchange,提问作者ronrun
相关产品推荐
相关产品推荐

