Installation:
composer require arrilot/laravel-widgets
php artisan vendor:publish --provider="Arrilot\Widgets\WidgetsServiceProvider" --tag="widgets-config"
Publish the config file to customize widget behavior (e.g., caching, async settings).
Generate a Widget:
php artisan make:widget RecentNews
This creates:
app/Widgets/RecentNews.php) extending AbstractWidget.resources/views/widgets/recent_news.blade.php).First Use Case: Register the widget in a controller or view composer:
use App\Widgets\RecentNews;
use Arrilot\Widgets\Facades\Widgets;
// In a controller:
public function dashboard()
{
Widgets::add('recent_news', RecentNews::class, ['config' => ['limit' => 5]]);
return view('dashboard');
}
Or directly in a view:
@widget('recent_news', ['config' => ['limit' => 5]])
Widget Registration:
Widgets::add() in controllers, middleware, or service providers.
Widgets::add('analytics', AnalyticsWidget::class, ['user_id' => auth()->id()]);
AppServiceProvider@boot() for app-wide reuse.
public function boot()
{
Widgets::register('sidebar', SidebarWidget::class);
}
Asynchronous Widgets:
Enable async loading in config/widgets.php:
'async' => true,
Use @widget directive with async:
@widget('recent_news', ['async' => true])
Reloadable Widgets:
Use Widgets::reload() to refresh widget data without reloading the entire page:
// Via AJAX
$.get('/widget/reload/recent_news', function(data) {
$('#widget-recent_news').html(data);
});
Ensure your widget class implements shouldReload():
public function shouldReload()
{
return request()->ajax();
}
Caching: Leverage built-in caching (Redis, file, etc.) via config:
'cache' => [
'driver' => 'file',
'minutes' => 60,
],
Widgets::clearCache('recent_news');
Data Passing:
config parameter:
Widgets::add('user_stats', UserStatsWidget::class, [
'user_id' => 1,
'metrics' => ['active', 'inactive']
]);
run() method to merge additional data:
public function run()
{
return view('widgets.user_stats', [
'user' => User::find($this->config['user_id']),
'metrics' => $this->config['metrics'],
]);
}
Conditional Rendering:
Use shouldRender() to control widget visibility:
public function shouldRender()
{
return auth()->check() && auth()->user()->isAdmin();
}
public function handle($request, Closure $next)
{
Widgets::add('notifications', NotificationWidget::class);
return $next($request);
}
@widget('live_chart', ['async' => true, 'data' => $chartData])
<script>
document.addEventListener('livewire:init', () => {
Livewire.on('chartUpdated', data => {
Widgets.reload('live_chart', { data });
});
});
</script>
$widget = Mockery::mock(RecentNews::class);
$widget->shouldReceive('run')->andReturn(view('widgets.mock_recent_news'));
Widgets::add('recent_news', $widget);
Caching Conflicts:
Widgets::clearCache() or adjust cache.minutes in config.storage/framework/cache/widgets/ for stale files.Async Loading Quirks:
@widget('recent_news', ['async' => true])
@include('widgets.fallback_recent_news')
routes/web.php (auto-generated by the package).Route Collisions:
/widget/reload/{name}. Conflicts may arise with existing routes.routes/web.php:
Route::widget('recent_news');
View Path Assumptions:
resources/views/widgets/{name}.blade.php.protected $view = 'custom.path.widget';
Configuration Overrides:
config/widgets.php may be overridden by per-widget settings.Widgets::config() to set defaults:
Widgets::config(['cache.minutes' => 30]);
Widget Not Rendering:
dd(Widgets::get('recent_news'));
shouldRender() returns true.Async Widgets Failing:
/widget/reload/{name}.shouldReload() logic is correct (e.g., request()->ajax()).Performance Issues:
public function run()
{
$start = microtime(true);
$data = $this->fetchData();
$time = microtime(true) - $start;
Log::debug("Widget executed in {$time}s");
return view(...);
}
Custom Directives:
Extend Blade directives by publishing the package’s views and modifying app/Providers/BladeServiceProvider.php:
public function boot()
{
Blade::directive('widget', function ($expression) {
return "<?php echo Arrilot\Widgets\Facades\Widgets::render($expression); ?>";
});
}
Widget Events:
Listen to widget events (e.g., widget.rendering, widget.rendered):
event(new WidgetRendering($widget));
Register listeners in EventServiceProvider.
Dynamic Widget Classes: Load widget classes dynamically based on user roles or other conditions:
$widgetClass = auth()->user()->isAdmin() ? AdminDashboardWidget::class : UserDashboardWidget::class;
Widgets::add('dashboard', $widgetClass);
API Widgets: Return JSON responses for API consumers:
public function run()
{
if (request()->wantsJson()) {
return response()->json(['data' => $this->fetchData()]);
}
return view(...);
}
Widget Dependencies:
Define dependencies between widgets (e.g., analytics requires user_data):
public function dependencies()
{
return ['user_data'];
}
Ensure dependencies are registered first:
Widgets::add('user_data', UserDataWidget::class);
Widgets::add('analytics', AnalyticsWidget::class);
How can I help you explore Laravel packages today?