Підготовка даних для Early View за допомогою Laravel View Creators

Перекладено ШІ
Оригінал: Laravel News
Оновлено: 17 липня, 2025
Вам цікаво дізнатися, як використовувати Laravel View Creators для покращення управління даними у ваших проєктах? У цій статті ми розглянемо, як правильно впроваджувати View Creators для оптимізації рендерингу ваших шаблонів, створюючи більш ефективні та функціональні додатки

Laravel View Creators виконуються одразу після ініціалізації виглядів, що забезпечує більш ранню точку для впровадження даних у порівнянні з View Composers, сприяючи підготовці критично важливої інформації для процесу рендерингу виглядів.

View Creators відрізняються від View Composers часом виконання: вони запускаються відразу після ініціалізації вигляду, а не тільки перед рендерингом:

use Illuminate\Support\Facades\View;
use App\View\Creators\UserDataCreator;

public function boot()
{
    View::creator('dashboard', UserDataCreator::class);
}

Створіть відповідний клас Creator з підтримкою впровадження залежностей через конструктор.

namespace App\View\Creators;

use App\Services\UserMetricsService;
use Illuminate\View\View;

class UserDataCreator
{
    protected $metricsService;

    public function __construct(UserMetricsService $metricsService)
    {
        $this->metricsService = $metricsService;
    }

    public function create(View $view)
    {
        $view->with('totalUsers', $this->metricsService->getTotalCount());
    }
}

Ось повна система віджетів для бокової панелі, яка демонструє можливості View Creator:

namespace App\View\Creators;

use Illuminate\View\View;
use App\Services\WidgetService;
use App\Services\PermissionService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;

class SidebarCreator
{
    protected $widgetService;
    protected $permissionService;

    public function __construct(WidgetService $widgetService, PermissionService $permissionService)
    {
        $this->widgetService = $widgetService;
        $this->permissionService = $permissionService;
    }

    public function create(View $view)
    {
        $user = Auth::user();

        if (!$user) {
            $view->with('sidebarWidgets', []);
            return;
        }

        $cacheKey = "sidebar_widgets_user_{$user->id}";

        $widgets = Cache::remember($cacheKey, 300, function () use ($user) {
            return $this->buildUserWidgets($user);
        });

        $view->with('sidebarWidgets', $widgets);
        $view->with('widgetPermissions', $this->permissionService->getUserWidgetPermissions($user));
    }

    private function buildUserWidgets($user)
    {
        $availableWidgets = $this->widgetService->getAvailableWidgets();
        $userPreferences = $user->widget_preferences ?? [];

        $widgets = [];

        foreach ($availableWidgets as $widget) {
            if (!$this->permissionService->canAccessWidget($user, $widget['key'])) {
                continue;
            }

            $isEnabled = $userPreferences[$widget['key']]['enabled'] ?? $widget['default_enabled'];
            $position = $userPreferences[$widget['key']]['position'] ?? $widget['default_position'];

            if ($isEnabled) {
                $widgets[] = [
                    'key' => $widget['key'],
                    'title' => $widget['title'],
                    'component' => $widget['component'],
                    'position' => $position,
                    'data' => $this->widgetService->loadWidgetData($widget['key'], $user),
                    'refresh_interval' => $widget['refresh_interval'] ?? 300
                ];
            }
        }

        usort($widgets, fn($a, $b) => $a['position'] <=> $b['position']);

        return $widgets;
    }
}

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        View::creator('layouts.main', SidebarCreator::class);
        View::creator('layouts.dashboard', SidebarCreator::class);
    }
}

class WidgetService
{
    public function getAvailableWidgets()
    {
        return [
            [
                'key' => 'recent_activity',
                'title' => 'Recent Activity',
                'component' => 'widgets.recent-activity',
                'default_enabled' => true,
                'default_position' => 1,
                'refresh_interval' => 60
            ],
            [
                'key' => 'performance_metrics',
                'title' => 'Performance Metrics',
                'component' => 'widgets.performance-metrics',
                'default_enabled' => false,
                'default_position' => 2,
                'refresh_interval' => 300
            ],
            [
                'key' => 'notifications_summary',
                'title' => 'Notifications',
                'component' => 'widgets.notifications-summary',
                'default_enabled' => true,
                'default_position' => 3,
                'refresh_interval' => 30
            ]
        ];
    }

    public function loadWidgetData($widgetKey, $user)
    {
        return match($widgetKey) {
            'recent_activity' => $this->getRecentActivity($user),
            'performance_metrics' => $this->getPerformanceMetrics($user),
            'notifications_summary' => $this->getNotificationsSummary($user),
            default => []
        };
    }

    private function getRecentActivity($user)
    {
        return $user->activities()
            ->latest()
            ->limit(5)
            ->with('subject')
            ->get()
            ->map(fn($activity) => [
                'description' => $activity->description,
                'created_at' => $activity->created_at->diffForHumans(),
                'subject_type' => class_basename($activity->subject_type),
                'icon' => $this->getActivityIcon($activity->description)
            ]);
    }

    private function getPerformanceMetrics($user)
    {
        return [
            'tasks_completed_today' => $user->tasks()->whereDate('completed_at', today())->count(),
            'average_completion_time' => $user->tasks()->avg('completion_time_minutes'),
            'productivity_score' => $this->calculateProductivityScore($user),
            'weekly_trend' => $this->getWeeklyTrend($user)
        ];
    }

    private function getNotificationsSummary($user)
    {
        $unreadCount = $user->unreadNotifications()->count();
        $priorityCount = $user->unreadNotifications()->where('data->priority', 'high')->count();

        return [
            'unread_total' => $unreadCount,
            'high_priority' => $priorityCount,
            'latest_notifications' => $user->notifications()
                ->limit(3)
                ->get()
                ->map(fn($notification) => [
                    'title' => $notification->data['title'] ?? 'Notification',
                    'time' => $notification->created_at->diffForHumans(),
                    'read' => !is_null($notification->read_at)
                ])
        ];
    }
}

View Creators прекрасно підходять для підготовки базових даних, від яких залежить подальша логіка вигляду, оптимізуючи процес рендерингу та забезпечуючи стабільну доступність даних у вашому додатку на Laravel