View Composers
تزریق خودکار داده به viewها با View Composers
View Composers به شما امکان میدهند که به صورت خودکار داده را به viewها تزریق کنید. این الگو به شما کمک میکند که data sharing را centralize کنید و از تکرار کد در controllers جلوگیری کنید.
انواع View Composers:
1. Closure-based Composers: Composers ساده با closure که برای logic ساده مناسب هستند.
2. Class-based Composers: Composers مبتنی بر کلاس که برای logic پیچیدهتر و reusable logic مناسب هستند.
استفادههای رایج:
- دادههای مشترک در چند view (مثل categories، menus)
- Navigation menus
- User settings
- Statistics و counters
- Sidebar content
- Footer data
- Global variables
مزایای View Composers:
- کاهش code duplication در controllers
- Centralized data sharing
- کد تمیزتر و maintainableتر
- Reusable logic
- Separation of concerns
- آسانتر برای testing
مثالها
Closure-based Composer
<?php
// In AppServiceProvider boot()
use Illuminate\Support\Facades\View;
View::composer('layouts.sidebar', function ($view) {
$view->with('categories', Category::all());
});
// Multiple views
View::composer(['layouts.sidebar', 'layouts.nav'], function ($view) {
$view->with('categories', Category::all());
});
// All views
View::composer('*', function ($view) {
$view->with('currentUser', auth()->user());
});
یک composer ساده که categories را به sidebar تزریق میکند.
Class-based Composer
<?php
namespace App\View\Composers;
use App\Models\Category;
use Illuminate\View\View;
class CategoryComposer
{
public function compose(View $view)
{
$view->with('categories', Category::all());
}
}
// Register in AppServiceProvider
View::composer('layouts.sidebar', CategoryComposer::class);
// Or with dependency injection
class CategoryComposer
{
public function __construct(
private CategoryRepository $repository
) {}
public function compose(View $view)
{
$view->with('categories', $this->repository->all());
}
}
یک composer مبتنی بر کلاس.
Composer با Caching
<?php
namespace App\View\Composers;
use Illuminate\View\View;
use Illuminate\Support\Facades\Cache;
class CategoryComposer
{
public function compose(View $view)
{
$categories = Cache::remember('categories', 3600, function () {
return Category::all();
});
$view->with('categories', $categories);
}
}
Composer با caching برای performance بهتر.
Multiple Composers
<?php
// Multiple composers for same view
View::composer('layouts.app', CategoryComposer::class);
View::composer('layouts.app', MenuComposer::class);
View::composer('layouts.app', function ($view) {
$view->with('siteSettings', config('site'));
});
// All composers execute and merge data
چند composer برای یک view.
Composer Creators
<?php
// View creator (runs before view is created)
View::creator('layouts.app', function ($view) {
// This runs before view is created
// Can modify view data before rendering
$view->with('preloadData', [
'user' => auth()->user(),
'settings' => app('settings')
]);
});
// Difference:
// Composer: runs after view is created
// Creator: runs before view is created
View creator که قبل از ایجاد view اجرا میشود.
Conditional Composer
<?php
namespace App\View\Composers;
use Illuminate\View\View;
class AdminComposer
{
public function compose(View $view)
{
if (auth()->check() && auth()->user()->isAdmin()) {
$view->with('adminMenu', $this->getAdminMenu());
$view->with('adminStats', $this->getAdminStats());
}
}
private function getAdminMenu()
{
return [
'users' => route('admin.users.index'),
'posts' => route('admin.posts.index'),
];
}
}
Composer با conditional logic.
Composer با Wildcards
<?php
// All views in users directory
View::composer('users.*', function ($view) {
$view->with('userCount', User::count());
});
// All views
View::composer('*', function ($view) {
$view->with('appName', config('app.name'));
});
// Multiple patterns
View::composer(['users.*', 'admin.*'], function ($view) {
$view->with('isAdminArea', true);
});
استفاده از wildcards برای matching چند view.
Testing Composers
<?php
namespace Tests\Unit;
use App\View\Composers\CategoryComposer;
use App\Models\Category;
use Illuminate\View\View;
use Tests\TestCase;
class CategoryComposerTest extends TestCase
{
public function test_composer_injects_categories()
{
Category::factory()->count(3)->create();
$view = $this->view('layouts.sidebar');
$composer = new CategoryComposer();
$composer->compose($view);
$this->assertArrayHasKey('categories', $view->getData());
$this->assertCount(3, $view->getData()['categories']);
}
}
Testing View Composers.
موارد استفاده
- دادههای مشترک در چند view
- Navigation menus و sidebar content
- Global variables و settings
- User-specific data
- Statistics و counters
- Footer و header data
اشتباهات رایج
- استفاده از composer برای data که فقط در یک view نیاز است
- Heavy operations در composer که باعث slow rendering میشود
- عدم استفاده از caching برای expensive queries
- Composer برای همه views که باعث overhead میشود
- فراموش کردن register کردن composer
- N+1 queries در composer
بهترین روشها
- از composer برای shared data استفاده کنید
- از caching برای expensive queries استفاده کنید
- از eager loading برای relationships استفاده کنید
- Composer را در Service Provider register کنید
- از class-based composer برای complex logic استفاده کنید
- Composer را test کنید
- از wildcards با احتیاط استفاده کنید
موارد خاص
- Multiple composers برای یک view
- Composer با circular dependencies
- Composer در API responses
- Composer با very large datasets
- Conditional composers
- Composer با async operations
نکات عملکرد
- Composer overhead معمولاً کم است
- استفاده از caching برای expensive queries مهم است
- Composer برای همه views میتواند overhead داشته باشد
- از eager loading برای relationships استفاده کنید
- Composer caching میتواند performance را بهبود دهد
نکات امنیتی
- مطمئن شوید که sensitive data در composer expose نمیشود
- از authorization checks در composer استفاده کنید
- مطمئن شوید که user input validated میشود
نکات مصاحبه
- تفاوت بین composer و creator چیست؟
- چه زمانی باید از View Composer استفاده کرد؟
- تفاوت بین closure-based و class-based composer چیست؟
- چگونه میتوان composer را test کرد؟
- مزایای استفاده از View Composers چیست؟
- چگونه میتوان composer را برای چند view register کرد؟
یادداشتهای نسخه
- Laravel 11.x: بهبود performance در composer execution
- Laravel 11.x: پشتیبانی بهتر از composer caching
- Laravel 10.x: بهبود composer registration
- Laravel 9.x: بهبود composer creators