Laravel 11’e geçtiğimde mail gönderme tarafında küçük ama etkisi büyük bir değişiklikle karşılaştım. Yıllardır alıştığım build() metodunun yerini artık envelope(), content() ve attachments() metodları almıştı. İlk gördüğümde “Neden böyle bir değişiklik yapılmış?” diye düşündüm, sonra kodu parçalayınca aslında mantığının oldukça temiz olduğunu fark ettim.
Bu yazıda, eski build() yapısından yeni üçlü yapıya geçişi kendi deneyimim üzerinden anlatacağım.
Neden Böyle Bir Değişiklik Yapılmış?
Laravel 11’e geçerken mail sınıflarını incelerken şunu gördüm: Artık her şey tek bir build() zincirine sıkıştırılmamış. Mail’in konusu, içeriği ve ekleri ayrı ayrı metodlara bölünmüş.
Benim gözlemlediğim avantajlar:
- Kod çok daha okunabilir hale gelmiş
- Return type’lar sayesinde tip güvenliği artmış
- Her metodun tek bir sorumluluğu var
- IDE autocomplete çok daha sağlıklı çalışıyor
Özellikle büyük projelerde uzun build() zincirleri arasında kaybolduğumu hatırlıyorum. Yeni yapıda bu karmaşa ortadan kalkmış.
Eski Yapı: build() İçinde Her Şey
Laravel 8–10 arasında genelde şöyle yazıyordum:
public function build()
{
return $this->subject('Hoş Geldiniz!')
->from('noreply@example.com', 'Örnek Şirket')
->replyTo('support@example.com')
->view('emails.welcome')
->with([
'userName' => $this->user->name,
'orderNumber' => $this->orderDetails['order_number'],
'totalAmount' => $this->orderDetails['total'],
])
->attach('/path/to/file.pdf');
}
Bu yapı çalışıyordu ama zamanla şunu fark ettim:
- Zincir uzadıkça okunabilirlik düşüyor
- Return type olmadığı için IDE tarafı zayıf kalıyor
- Test yazmak zorlaşıyor
- Herşey tek bir metoda sıkışıyor
Özellikle 8–10 satırlık zincirler bir süre sonra yorucu hale geliyordu.
Yeni Yapı: envelope(), content(), attachments()
Laravel 11’e geçtiğimde mail sınıfını şu şekilde düzenledim.
1. envelope() — Zarf Bilgileri
Önce subject, from, replyTo gibi bilgileri envelope() metoduna taşıdım:
public function envelope(): Envelope
{
return new Envelope(
subject: 'Hoş Geldiniz!',
from: new Address('noreply@example.com', 'Örnek Şirket'),
replyTo: [
new Address('support@example.com', 'Destek Ekibi'),
],
);
}
2. content() — İçerik
Eski view() ve with() zincirini şu şekilde ayırdım:
public function content(): Content
{
return new Content(
view: 'emails.welcome',
with: [
'userName' => $this->user->name,
'orderNumber' => $this->orderDetails['order_number'],
'totalAmount' => $this->orderDetails['total'],
],
);
}
Bu bölümü ayırınca şunu fark ettim:
Mail’in içeriği artık gerçekten “sadece içerik” ile ilgili.
Ayrıca public property kullandığım yerlerde with yazmaya bile gerek kalmadığını gördüm. Eğer değişken zaten public ise view içinde otomatik erişilebiliyor.
3. attachments() — Ekler
Eskiden attach(), attachFromStorage() gibi zincirleri build() içine yazıyordum. Şimdi ayrı bir metod var:
public function attachments(): array
{
return [
Attachment::fromPath('/path/to/file.pdf')
->as('fatura.pdf')
->withMime('application/pdf'),
];
}
Bunu ayırınca kod gerçekten daha temiz göründü. Mail’in ekleri artık açıkça tek bir yerde tanımlanıyor.
Geçiş Yaparken Yaptığım Hatalar
Geçiş sırasında birkaç klasik hataya düştüm:
Hem build() hem yeni metodları bırakmak
İlk etapta build() metodunu silmeden yeni metodları eklemiştim. Bu kafa karıştırıcı bir yapı oluşturdu. Sonra tamamen build() metodunu kaldırdım.
ReplyTo’yu string vermek
replyTo: 'test@example.com' // Hata
Bunu array olarak vermem gerektiğini sonradan fark ettim:
replyTo: [
new Address('test@example.com'),
]
attachments() return type unutmak
Return type’ı eklemeyince IDE tarafında uyarı aldım.
Şu şekilde düzelttim:
public function attachments(): array
Gerçek Bir Örnek: Randevu Bildirimi
Projelerimden birinde randevu maili gönderiyordum. Eski sistemde şöyleydi:
public function build()
{
return $this->subject('Randevunuz Oluşturuldu')
->view('emails.appointment')
->with([
'appointmentDate' => $this->appointment->date,
'studentName' => $this->student->name,
'teacherName' => $this->teacher->name,
'zoomLink' => $this->teacher->zoom_link,
]);
}
Laravel 11’e geçince şu şekilde değiştirdim:
public function envelope(): Envelope
{
return new Envelope(
subject: 'Randevunuz Oluşturuldu',
);
}
public function content(): Content
{
return new Content(
view: 'emails.appointment',
with: [
'appointmentDate' => $this->appointment->date,
'studentName' => $this->student->name,
'teacherName' => $this->teacher->name,
'zoomLink' => $this->teacher->zoom_link,
],
);
}
public function attachments(): array
{
return [];
}
Bu hali bana çok daha net göründü.
Artık biri sınıfa baktığında mail’in yapısını saniyeler içinde anlayabiliyor.
Named Arguments Detayı
Yeni yapı PHP 8’in named arguments özelliğini kullanıyor. Bu da bana şunu sağladı:
- Parametre sırası umurumda değil
- Sadece ihtiyacım olanı yazıyorum
return new Envelope(
from: new Address('test@example.com'),
subject: 'Test Mail',
);
Bu esneklik özellikle karmaşık maillerde hoşuma gitti.
Performans Konusu
Denemelerimde performans açısından belirgin bir fark görmedim.
Laravel her iki yapıda da mail’i aynı şekilde gönderiyor. Ama kod organizasyonu ciddi anlamda iyileşmiş.
Sonuç
Laravel 11’deki yeni Mailable yapısını ilk gördüğümde alışmam biraz zaman aldı. Özellikle build() metodunu bırakmak garip geldi. Ama birkaç sınıfı migrate ettikten sonra şunu net şekilde gördüm:
- Kod daha temiz
- Sorumluluklar net ayrılmış
- IDE desteği daha iyi
- Uzun vadede bakım daha kolay
Ben kendi projelerimde artık tamamen yeni syntax’ı kullanıyorum ve eski yapıya dönmek istemiyorum.
Geçiş Yapacaklar İçin Kısa Kontrol Listem
build()metodunu kaldırdım mı?envelope()metodunu ekledim mi?content()metodunu ekledim mi?attachments()metodunu ekledim mi?- Return type’ları doğru mu?
- Address nesnelerini doğru kullandım mı?
Laravel 11’e geçiş yapıyorsanız, mail sınıflarınızı da elden geçirmenizi öneririm. Baştan biraz alışma süreci var ama uzun vadede gerçekten daha düzenli bir yapı sunuyor.