Laravel. Как вызвать view()->share() только для администратора?
На сайте есть блок, скажем, с количеством новых публикаций за последние сутки. Он отображается на всех страницах, поэтому я передаю его в шаблон по view()->share().
Этот блок нужно показывать только администратору. Но сделать это нужно так, чтобы его отображение регулировалось не в шаблоне, а в коде, так как этот запрос довольно энергозатратный (на 500 мс). То есть нужно вообще не готовить данные к выводу для остальных пользователей.
Изначально я это делал в методе boot файла AppServiceProvider.php, но там не доступен Auth, которым можно было бы определить, является ли пользователь администратором.
Я решил перенести эту задачу в новый Middleware. Там Auth прекрасно работает, но только на обратном пути, уже после $response = $next($request); и перед return $response;.
Но в этом месте уже не срабатывают view()->share() так как их нужно привязывать к шаблонам до погружения в $next.
Собственно вопрос. Как можно всё переделать так, чтобы view()->share() работали вместе с проверками по Auth и чтобы все работало глобально по всему сайту, а не в определенных контроллерах?
Ответы (1 шт):
Можно сделать с помощью ViewComposer. https://laravel.com/docs/8.x/views#view-composers
Создаёте композер, в методе compose делаете нужные проверки и запросы, а потом вызываете из сервис провайдера Illuminate\Support\Facades\View::composer(). В качестве аргументов передаёте имя шаблона где надо выводить данные и созданный композер.
Пример
// Файл App\Http\Composers\TitleComposer - получение информации о заголовках 25 новейших новостей
namespace App\Http\ViewComposers;
use App\Models\News;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class TitleComposer
{
public function compose(View $view)
{
$titles = null;
if(Auth::user()->isAdmin())
{
$titles = News::select('title')->newest()->take(25)->get();
}
$view->with('titles', $titles);
}
}
// Файл App\Providers\AppServiceProvider
namespace App\Providers;
use App\Http\ViewComposers\TitleComposer;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer('layouts.news', TitleComposer::class);
}
}