Ön Hazırlık ve Gereksinimler
Projeye başlamadan önce sisteminizde Laravel 11 veya üzeri bir sürümün yüklü olduğundan emin olmalısınız. Ayrıca veritabanı yönetimi için MySQL veya PostgreSQL kullanmanız önerilir. Geliştirme ortamınızda PHP 8.2+ sürümünün aktif olması, modern tip tanımlamalarını (type hinting) kullanabilmemiz için gereklidir.
- Laravel 11.x framework
- Composer paket yöneticisi
- Veritabanı (MySQL/PostgreSQL)
- Temel düzeyde Eloquent ORM bilgisi
Veritabanı Tasarımı ve Migration İşlemleri
Rezervasyon sisteminin kalbi veritabanıdır. Randevuların tutulacağı tabloyu oluştururken zaman aralıklarını (başlangıç ve bitiş) ve kullanıcı ilişkisini doğru kurmalıyız. appointments adında bir tablo oluşturarak işe başlayalım.
php artisan make:migration create_appointments_table
Oluşturulan migration dosyasında, randevu tarihleri ve durum bilgisi için gerekli sütunları tanımlıyoruz. Aşağıdaki kod, veritabanı şemanızın nasıl görünmesi gerektiğini gösterir:
public function up(): void
{
Schema::create('appointments', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->dateTime('start_time');
$table->dateTime('end_time');
$table->string('status')->default('pending'); // pending, confirmed, cancelled
$table->timestamps();
});
}
Rezervasyon Çakışmalarını Önleme (Mantıksal Kontrol)
En kritik nokta, aynı zaman diliminde iki farklı kullanıcının randevu almasını engellemektir. Laravel'in where sorguları ile veritabanı seviyesinde bir çakışma kontrolü yapmalıyız. Bir randevunun çakışması için, yeni randevunun başlangıç saatinin mevcut bir randevunun bitişinden önce ve bitiş saatinin de mevcut randevunun başlangıcından sonra olması gerekir.
$isBooked = Appointment::where('start_time', '', $request->start_time)
->exists();
if ($isBooked) {
return back()->withErrors(['error' => 'Bu saat dilimi zaten dolu.']);
}
Form Doğrulama ve Güvenlik
Kullanıcıdan gelen verilerin doğruluğunu kontrol etmek, uygulamanın güvenliği için zorunludur. Laravel'in FormRequest sınıfını kullanarak tarihlerin geçmiş bir tarihe ait olup olmadığını ve mantıksal sırasını doğrulayabiliriz.
public function rules(): array
{
return [
'start_time' => 'required|date|after:now',
'end_time' => 'required|date|after:start_time',
];
}
Bu doğrulama, kullanıcıların geçmiş tarihe randevu almasını engeller ve end_time değerinin start_time değerinden sonra gelmesini garanti eder.
Rezervasyon Yönetimi İçin Karşılaştırma Tablosu
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Eloquent ORM Sorgusu | Okunabilir ve güvenli | Karmaşık sorgularda yavaşlayabilir |
| Database Transaction | Veri bütünlüğünü korur | Ekstra işlem yükü getirir |
| Caching (Redis) | Çok hızlıdır | Senkronizasyon zorluğu |
Veri Bütünlüğü İçin Transaction Kullanımı
Rezervasyon oluştururken sistemin bir hata anında tutarsız veri kaydetmesini önlemek için DB::transaction bloğunu kullanmalıyız. Bu, tüm işlemlerin başarıyla tamamlanmasını veya hata durumunda hiçbir şeyin kaydedilmemesini sağlar.
use Illuminate\Support\Facades\DB;
DB::transaction(function () use ($request) {
Appointment::create([
'user_id' => auth()->id(),
'start_time' => $request->start_time,
'end_time' => $request->end_time,
]);
});
Kritik Güvenlik Uyarısı: Kullanıcı girdilerini asla doğrudan veritabanı sorgularına dahil etmeyin. Laravel'in Eloquent ORM yapısını kullanmak, SQL Injection saldırılarına karşı otomatik koruma sağlar. Ayrıca, üretim ortamında (production) hata mesajlarını kullanıcıya göstermeyin; sadece log dosyalarına yazdırın.
Sıkça Sorulan Sorular
Randevu saatleri için hangi veritabanı tipi kullanılmalı?
Veritabanında timestamp veya datetime veri tiplerini kullanmak, Laravel'in Carbon kütüphanesi ile zaman manipülasyonu yapmanızı kolaylaştırır.
Aynı anda iki kullanıcı aynı saate tıklarsa ne olur?
Veritabanı seviyesinde "Unique" kısıtlamalar veya yukarıda gösterilen exists() kontrolü ile çakışmalar engellenir. Yüksek trafikli sitelerde lockForUpdate() metodu ile satır kilitleme (row locking) uygulanmalıdır.
Randevu hatırlatıcılarını nasıl yapabilirim?
Laravel'in Task Scheduling (görev zamanlayıcı) özelliğini kullanarak app/Console/Kernel.php üzerinde günlük veya saatlik hatırlatıcı mailler gönderebilirsiniz.
Rezervasyon iptali nasıl yönetilmeli?
Randevu tablosuna bir status sütunu ekleyerek, veriyi silmek yerine durumu 'cancelled' olarak güncellemek, veri analitiği için daha sağlıklıdır.
Mobil uyumluluk için neye dikkat etmeliyim?
Tarih seçimi için tarayıcıların yerel datetime-local inputlarını veya Flatpickr gibi modern JavaScript kütüphanelerini kullanabilirsiniz.
Performans Optimizasyonu ve İndeksleme Stratejileri
Rezervasyon sistemleri büyüdükçe, veritabanı sorgularının hızı kritik bir öneme sahip olur. Özellikle binlerce randevunun olduğu bir tabloda, belirli bir tarih aralığını sorgulamak ciddi bir yük oluşturabilir. Laravel'de appointments tablonuzda start_time ve end_time sütunlarına mutlaka indeks eklemelisiniz.
Migration dosyanızda indeksleme işlemini şu şekilde yapabilirsiniz:
Schema::table('appointments', function (Blueprint $table) {
$table->index('start_time');
$table->index('end_time');
$table->index(['user_id', 'status']); // Kullanıcı bazlı sorgular için
});
Ayrıca, çok sık sorgulanan veriler için Laravel'in Cache mekanizmasını kullanmak, veritabanı üzerindeki yükü %80 oranında azaltabilir. Örneğin, mevcut günün müsaitlik durumunu her seferinde veritabanından çekmek yerine 10 dakikalık süreyle önbelleğe alabilirsiniz:
$availableSlots = Cache::remember('slots_day_' . $date, 600, function () use ($date) {
return Appointment::whereDate('start_time', $date)->get();
});
Otomatik Testler ile Rezervasyon Mantığını Doğrulama
Rezervasyon sistemlerinde en büyük risk, "race condition" (yarış durumu) veya mantıksal hatalar nedeniyle aynı saate iki kişinin atanmasıdır. Bunu manuel test etmek yerine Laravel'in yerleşik Pest veya PHPUnit test araçlarını kullanmalısınız.
Aşağıdaki örnek, aynı saate iki farklı rezervasyon yapılmaya çalışıldığında sistemin hata verip vermediğini test eden bir birim testidir:
public function test_cannot_book_same_slot_twice()
{
$appointment = Appointment::factory()->create([
'start_time' => '2023-12-01 10:00:00',
'end_time' => '2023-12-01 11:00:00',
]);
$response = $this->post('/api/reserve', [
'start_time' => '2023-12-01 10:30:00',
'end_time' => '2023-12-01 11:30:00',
]);
$response->assertStatus(422);
$response->assertJsonFragment(['message' => 'Bu saat dilimi zaten dolu.']);
}
Bu testleri CI/CD süreçlerinize dahil ederek, kodunuzda yapacağınız herhangi bir değişikliğin rezervasyon mantığını bozmadığından emin olabilirsiniz. Özellikle DatabaseTransactions trait'ini kullanarak test sonrası veritabanınızın temiz kalmasını sağlayabilirsiniz.
İleri Düzey İpuçları: Kuyruk (Queue) Yapısı ile Bildirimler
Rezervasyon onaylandığında kullanıcıya e-posta göndermek veya SMS bildirimini tetiklemek, ana işlem süresini uzatabilir. Kullanıcının "Rezervasyon Yap" butonuna bastıktan sonra beklemesini engellemek için Laravel Queues (Kuyruklar) yapısını kullanmalısınız.
İşlemi arka plana atmak için şu adımları izleyin:
php artisan make:job SendBookingConfirmationkomutu ile bir Job oluşturun.- Rezervasyon controller içerisinde
dispatchmetodunu kullanın.
// AppointmentController.php
public function store(Request $request) {
$appointment = Appointment::create($validated);
// E-posta gönderimini kuyruğa ekle
SendBookingConfirmation::dispatch($appointment);
return response()->json(['status' => 'success']);
}
Bu yaklaşım, uygulamanızın daha ölçeklenebilir olmasını sağlar ve sunucu kaynaklarını daha verimli kullanmanıza olanak tanır.
Sonuç
Laravel ile dinamik bir randevu rezervasyon sistemi oluştururken veritabanı ilişkileri, form doğrulama ve veri bütünlüğü en önemli yapı taşlarıdır. Bu rehberde öğrendiğiniz yöntemlerle, çakışmaları engelleyen ve güvenli çalışan bir sistemin temelini attınız. Bir sonraki adım olarak, randevular için bir takvim görünümü (FullCalendar gibi) entegre ederek kullanıcı deneyimini daha ileri bir seviyeye taşıyabilirsiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kodlar eğitim amaçlıdır. Canlıya almadan önce mutlaka kapsamlı bir güvenlik testinden geçirin ve veritabanı yedeklerinizi düzenli olarak alın.


Yorumlar (0)
Yorum Yaz