-1

Using Laravel 5.6, I'm trying to get the number of received links a logged-in user may have in my application.

public function getReceivedLinksCount() {
    return $count = App\Link::where([
                ['recipient_id', Auth::id()],
                ['sender_id', '!=', Auth::id()]
            ])->count();
}

So far, so good. Question is not about that piece of code, but where I can use it. I'd like to display this counter on the navigation bar of the website (Facebook's style) which is in my header.blade.php which is included in every page.

I'd like to do it with a clean code, of course. It seems like I need to use View Composers but I'm not sure it's the right way to do it, and not sure on how the code is supposed to look.

Pierre Le Bot
  • 294
  • 1
  • 5
  • 20

2 Answers2

1
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        view()->composer('layouts.header', function ($view) {
            $view->with('variable_name', \App\Path-To-Your-Model::something());
        });
    }
kenken9999
  • 765
  • 1
  • 6
  • 14
  • Your answer works well but with more recent (I guess) code : I used `View::composer` instead of `view()->composer`. Thanks. – Pierre Le Bot Jun 16 '18 at 12:22
  • if use View:: you need add -> use Illuminate\Support\Facades\View; to top of your class, use view() helper no need add that line and is same effect, and the difference of View::share is View::share is global the variable, view()->composer('name of the blade_this accept array too') means ONLY generate the variable when load the header blade – kenken9999 Jun 16 '18 at 17:51
  • 1
    so for example if you load admin_header.blade.php, you don't have this variable, because you may don't need that – kenken9999 Jun 16 '18 at 17:56
0

You can share a value across all views by using View::share(), see docs

For example

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        $linksCount = Link::getReceivedLinksCount();
        View::share('linksCount', $linksCount);
    }

    ...

}

This works well if you want to set the value everywhere. Personally, I would set the value in the constructor of a 'BaseController' that gets extended by other controllers. This makes the code more discoverable because most people would expect view values to be set in a controller. And it's also a bit more flexible if you plan on having a section of your app that doesn't require that value to be computed.

321zeno
  • 1,264
  • 1
  • 12
  • 24
  • Is it the same as doing `@inject('count', 'App\Http\Controllers\LinkController')` like explained in [Blade's injection doc](https://laravel.com/docs/5.6/blade#service-injection)? I find it a little bit ugly, no? – Pierre Le Bot Jun 14 '18 at 17:33
  • I find the controller approach better because you wouldn't have to update the views if you refactor the code that generates the count (for example change the class name or method name or whatever) – 321zeno Jun 15 '18 at 11:21
  • Ok! What's the difference between your code and the other answer from kenken9999 ? Also, what would you recommend between adding the piece of code in AppServiceProvider or in a separate service provider? – Pierre Le Bot Jun 15 '18 at 14:25