Laravel View Composer 为每个视图复制 SQL 查询

Posted

技术标签:

【中文标题】Laravel View Composer 为每个视图复制 SQL 查询【英文标题】:Laravel View Composer duplicating SQL queries for every view 【发布时间】:2018-03-11 17:13:03 【问题描述】:

我需要在大多数视图中访问一些数据(用户详细信息)。我做了什么:

我创建了 ComposerServiceProvider

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    
        view()->composer(
            ['includes.header','profile'],
            'App\Http\ViewComposers\CustomerComposer'
        );

    

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    
        //
    

创建 CustomerComposer 类

<?php

namespace App\Http\ViewComposers;

use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use Modules\Customers\Entities\CustomerDetail;

class CustomerComposer

    public $customer = [];

    /**
     * Bind data to the view.
     *
     * @param  View  $view
     * @return void
     */
    public function compose(View $view)
    
        $user = Auth::guard('customer');

        $this->customer = CustomerDetail::where('user_id',$user->id())->first();

        $view->with( 'customer', $this->customer );
    

一切正常,但是当我查看调试栏时,它会显示每个视图执行的相同查询,例如,如果我定义 ['includes.header','profile'] 如果 ['includes.header ','profile','something_else'] 3 次等等...

在这种情况下,查询是

select * from `customer_details` where `user_id` = '1' limit 1
select * from `customer_details` where `user_id` = '1' limit 1

如果我提供通配符

view()->composer(
            ['*'],
            'App\Http\ViewComposers\CustomerComposer'
        );

它将生成 23 个查询!我错过了什么?

【问题讨论】:

【参考方案1】:

好的,我想我找到了解决方案。在 ComposerServiceProvider 类中:

/**
* Register the application services.
*
* @return void
*/
public function register()

    $this->app->singleton(\App\Http\ViewComposers\CustomerComposer::class);

那个。

在 Laravel 文档中

注册一个单例

有时,您可能希望将某些内容绑定到容器中 应该只解析一次,并且应该返回相同的实例 在随后调用容器时:

【讨论】:

【参考方案2】:

根据https://laravel.com/docs/5.5/views#view-composers 的手册:

“视图合成器是在渲染视图时调用的回调或类方法。如果您有想要绑定到视图的数据每次渲染视图时,视图合成器可以帮助您将该逻辑组织到一个位置。”

(强调我的)

在这种情况下:

    view()->composer(
        ['includes.header','profile'],
        'App\Http\ViewComposers\CustomerComposer'
    );

您正在附加includes.header 视图和profile 视图,我猜其中包括includes.header 视图。因此,由于 composer 在视图渲染时执行,它会执行两次,一次是在渲染 profile 视图时,另一次是在渲染 includes.header 视图时。

【讨论】:

我明白这一点,但是将数据从模型传递到所有视图的最有效方法是什么?我虽然这个实现是为此而做的,但我必须在这里遗漏一些明显的东西。【参考方案3】:

您可以在此处使用配置来解决视图组合的多次查询运行问题。比如下面的代码。

公共函数撰写(查看$view)

if(!Config::has('composeVars')) 

    Config::set('composeVars') = [
      'users' => User::all();  
    ];


$view->with('*', Config::get('composeVars'));

【讨论】:

以上是关于Laravel View Composer 为每个视图复制 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

php Laravel View Composer

在扩展布局的视图中无法访问Laravel View Composer变量

Laravel View Composer“使用未定义的常量”

带有存储库的 Laravel View Composer 不工作;

View Composer 在我的 Laravel 应用程序中不起作用

将 Laravel 集合/数组转换为 Javascript 数组