介绍 Laravel 中的视图组件,作为视图组合器的替代方案
发布日期:作者: Jeff
在软件开发中,“最佳实践”之一是创建可重用的代码,这些代码可以在需要时在应用程序的不同部分中实现。
想象一下,您有一个博客,您需要在侧边栏上显示一个“亮点”小部件。
这些“亮点”将使用 API 响应进行填充。
因此,在您的主页控制器中,您可能会有类似以下内容
<br></br><?php class HomeController extends Controller { protected $blog; public function __construct(BlogRepository $blog) { $this->blog = $blog } public function index() { return view('blog', [ 'posts' => $blog->latest(), 'highlights' => $blog->highlights() ]); }}
简洁明了,但这在您需要将相同的“亮点”变量传递到您网站的每个页面(例如,联系页面)时会开始成为问题。
<?php class ContactPageController extends Controller { protected $blog; public function __construct(BlogRepository $blog) { $this->blog = $blog } public function index() { return view('contact', [ 'highlights' => $blog->highlights() ]); }}
想象一下,如果您有 20 个不同的控制器会发生什么?您最终可能会遇到大量的代码重复,并且随着应用程序的增长,它将变得更难维护。
使用 Laravel 的视图组合器
视图组合器允许您将逻辑移到控制器之外,并将数据传递到指定的视图集。
<?php class HighLightsComposer{ protected $users; public function __construct(BlogRepository $blog) { $this->blog = $blog } public function compose(View $view) { $view->with('highlights', $this->blog->highlights()); }}
然后,在您的服务提供者中,您将拥有类似以下内容
<?php class ComposerServiceProvider extends ServiceProvider{ public function boot() { View::composer( 'highlights', 'App\Http\ViewComposers\HighlighsComposer' ); }}
此时,您可以像这样重构您的控制器
<?php class HomeController extends Controller { protected $blog; public function __construct(BlogRepository $blog) { $this->blog = $blog } public function index() { return view('blog', [ 'posts' => $blog->latest() ]); }} class ContactPageController extends Controller { public function index() { return view('contact'); } }
思考产品
乍一看,这似乎很棒,但让我们仔细想想。
当您使用“视图组合器”时,这个过程有点像魔法,并在应用程序中一个不那么明显的部分运行,特别是对于那些没有太多使用 Laravel 经验的人来说。
想象一下,您的客户要求您将“亮点”小部件的内容替换为静态内容。在当前示例中,您只需更新“highlights.blade.php”文件的内容即可。
应用程序将按预期工作,但是,API 调用将在后台(在视图组合器中)运行。
因此,无论您是否从视图中删除逻辑,您都需要更改视图的名称,或更新服务提供者以停止来自视图组合器的 API 调用。
使用视图组件
以下是我目前正在使用的一个项目中正在使用的一种方法,我编造了这个名字,您可以随意称呼它。
我们想要的是重用一个通用视图,该视图将使用动态数据(来自任何资源)构建。
Highlights
组件类
创建一个新的 这些“视图组件”类可以共享一个接口或契约来指定我们想要返回的数据类型。在这种情况下,Laravel 的 Htmlable
契约非常适合。
<?php namespace App\ViewComponents; use Illuminate\Support\Facades\View;use Illuminate\Contracts\Support\Htmlable; class HighlightsComponent implements Htmlable{ protected $blog; public function __construct(BlogRepository $blog) { $this->blog = $blog; } public function toHtml() { return View::make('highlights') ->with('highlights', $this->blog->highlights()) ->render(); }}
创建一个新的 blade 指令来渲染视图组件
由于我们在上面的类中使用了依赖注入,因此最好使用 IOC 为我们解析这些依赖项。
<?php class AppServiceProvider extends ServiceProvider{ public function register() { Blade::directive('render', function ($component) { return "<?php echo (app($component))->toHtml(); ?>"; }); }}
最后,您可以“渲染”视图组件,它将在任何视图上返回一个 HTML 部分。
// home.blade.php @render(\App\ViewComponents\HighlightsComponent::class)
总结
使用这种方法,您可以在应用程序中的任何视图上重用使用动态数据的复杂组件。
组件逻辑只有在通过 @render()
blade 指令包含时才会运行。
如果您与一个大型开发人员团队合作,您可以确保,如果任何人更改视图中小部件的实现而无需更新后端的实现,您的应用程序的性能不会受到影响。