⏰ Trial Bitirme Yöntemleri

Cron Çalışmazsa Ne Olur? - Tüm Alternatifler

❌ Cron Çalışmazsa Ne Olur?

🚨 SORUN:
  • Trial bitmiyor: 7 gün geçti ama kullanıcı hala premium gibi kullanıyor!
  • Status güncellenmiyor: active olarak kalıyor, expired olmuyor
  • Gelir kaybı: Kullanıcılar ücretsiz premium kullanıyor
  • Haksız kullanım: Sistemin amacı bozuluyor
💡 Neden Cron Çalışmayabilir?
  • Sunucu cron servisi devre dışı
  • Cron job yanlış kurulmuş
  • Laravel schedule çalışmıyor
  • Shared hosting cron kısıtlaması
  • Sunucu yeniden başlatıldı, cron unutuldu

🎯 4 Farklı Yaklaşım

Yaklaşım 1: Cron Job (Klasik)

Her gün belirli saatte çalışan otomatik script.

// app/Console/Kernel.php protected function schedule(Schedule $schedule) { $schedule->call(function () { Subscription::whereHas('plan', fn($q) => $q->where('is_trial', true)) ->where('status', 'active') ->whereDate('ends_at', '<=', now()) ->update(['status' => 'expired']); })->daily(); } // Crontab * * * * * php /path/to/artisan schedule:run

✅ Artıları:

  • Zamanında çalışır (her gün aynı saatte)
  • Performans etkisi yok (arka planda)
  • Profesyonel yaklaşım

❌ Eksileri:

  • Cron çalışmazsa sistem durur!
  • Shared hosting'de sorunlu olabilir
  • Kurulum gerektirir

Yaklaşım 2: Lazy Check (Kontrol Sırasında)

Trial kontrolü yapılırken otomatik expire eder.

// User model public function isPremium(): bool { // Aktif subscription var mı? $subscription = $this->subscriptions() ->where('status', 'active') ->first(); if (!$subscription) { return false; } // 🔥 LAZY CHECK: Bitmiş mi kontrol et! if ($subscription->ends_at < now()) { // Otomatik expire et $subscription->update(['status' => 'expired']); return false; } return true; }

✅ Artıları:

  • CRON GEREKSIZ! Her kontrol sırasında otomatik
  • Her zaman çalışır (kullanıcı siteye girdiğinde)
  • Shared hosting'de sorunsuz
  • Kurulum gerektirmez

❌ Eksileri:

  • Kullanıcı siteye girmezse expire olmaz (nadir)
  • Her kontrol sırasında ekstra sorgu (minimal)

Yaklaşım 3: Middleware (Her İstek)

Her HTTP isteğinde arka planda kontrol eder.

// app/Http/Middleware/CheckExpiredTrials.php public function handle($request, Closure $next) { // Sadece auth kullanıcı için if (auth()->check()) { $user = auth()->user(); // Trial subscription var mı? $trialSubscription = $user->subscriptions() ->whereHas('plan', fn($q) => $q->where('is_trial', true)) ->where('status', 'active') ->first(); if ($trialSubscription && $trialSubscription->ends_at < now()) { $trialSubscription->update(['status' => 'expired']); } } return $next($request); }

✅ Artıları:

  • Gerçek zamanlı (her istek)
  • Cron gerektirmez
  • Otomatik çalışır

❌ Eksileri:

  • Her istekte DB sorgusu (performans)
  • Gereksiz yük (her sayfa yüklenişinde)

Yaklaşım 4: Database Scope (Akıllı Sorgu)

Database seviyesinde otomatik filtreleme.

// Subscription model public function scopeActive($query) { return $query->where('status', 'active') ->where(function($q) { // Bitiş tarihi gelmemişse VEYA null ise $q->where('ends_at', '>', now()) ->orWhereNull('ends_at'); }); } // Kullanım $activeSubscriptions = $user->subscriptions()->active()->get(); // Bitmiş trial'lar otomatik filtrelenir!

✅ Artıları:

  • Gerçek zamanlı (sorgu sırasında)
  • Cron gerektirmez
  • Performanslı (DB seviyesinde)

❌ Eksileri:

  • Status güncellenmiyor (sadece filtreliyor)
  • Raporlama karışık (status hala active)

📊 Karşılaştırma Tablosu

Özellik Cron Job Lazy Check Middleware DB Scope
Cron Gerekli mi? ✗ Evet ✓ Hayır ✓ Hayır ✓ Hayır
Gerçek Zamanlı ✗ Günde 1 ✓ Kontrol sırasında ✓ Her istek ✓ Sorgu sırasında
Performans ✓ Mükemmel ✓ İyi ✗ Orta ✓ İyi
Status Güncelleme ✓ Evet ✓ Evet ✓ Evet ✗ Hayır
Shared Hosting ✗ Sorunlu ✓ Sorunsuz ✓ Sorunsuz ✓ Sorunsuz
Raporlama ✓ Net ✓ Net ✓ Net ✗ Karışık

🎯 ÖNERİLEN: Hibrit Çözüm

✅ Lazy Check + Cron Job (İkisini Birlikte Kullan!)

En güvenli yaklaşım: Her iki yöntemi de kullan!

🔥 Lazy Check (Ana Güvenlik)

isPremium() metodunda kontrol:

if ($subscription->ends_at < now()) { $subscription->update([ 'status' => 'expired' ]); return false; }

Görevi: Kullanıcı siteye girdiğinde otomatik kontrol

⏰ Cron Job (Yedek Güvenlik)

Günlük 00:00'da çalışan script:

$schedule->call(function () { Subscription::expireTrials(); })->daily();

Görevi: Siteye girmeyen kullanıcıları da kontrol et

💡 Neden İkisi Birlikte?
  • Lazy Check: Kullanıcı siteye girdiğinde anında kontrol (gerçek zamanlı)
  • Cron Job: Siteye girmeyen kullanıcılar için yedek (toplu temizlik)
  • Cron çalışmazsa: Lazy check devreye girer, sorun olmaz!
  • Kullanıcı girmezse: Cron job devreye girer, yine sorun olmaz!

💻 Hibrit Çözüm - Kod Örneği

1. User Model (Lazy Check)

// app/Models/User.php public function isPremium(): bool { if (!$this->isMuzibuTenant()) { return false; } $subscription = $this->subscriptions() ->where('status', 'active') ->where('ends_at', '>', now()) // Bitişi gelmiş olanları alma! ->first(); // 🔥 LAZY CHECK: Bitmiş ama status active kalanları temizle $expiredSubscription = $this->subscriptions() ->where('status', 'active') ->where('ends_at', '<=', now()) ->first(); if ($expiredSubscription) { $expiredSubscription->update(['status' => 'expired']); } return $subscription ? true : false; }

2. Subscription Model (Helper Method)

// app/Models/Subscription.php public static function expireTrials() { $expired = self::whereHas('plan', function($q) { $q->where('is_trial', true); }) ->where('status', 'active') ->where('ends_at', '<=', now()) ->get(); foreach ($expired as $subscription) { $subscription->update(['status' => 'expired']); // Log \Log::info("Trial expired for user: {$subscription->user_id}"); } return $expired->count(); }

3. Cron Job (Yedek)

// app/Console/Kernel.php protected function schedule(Schedule $schedule) { $schedule->call(function () { $count = \App\Models\Subscription::expireTrials(); \Log::info("Expired {$count} trial subscriptions via cron"); })->daily(); }
✅ Sonuç:
  • Kullanıcı siteye girer: Lazy check devreye girer → Trial expire
  • Kullanıcı 1 hafta girmez: Cron job devreye girer → Trial expire
  • Cron çalışmaz: Sorun yok! Lazy check her zaman çalışır
  • Kullanıcı hiç gelmez: Cron job temizler (önemli değil zaten)

✅ SON KARAR

🎯 Hibrit Yaklaşım: Lazy Check + Cron Job

Ana Güvenlik: Lazy Check

  • isPremium() metodunda otomatik kontrol
  • Kullanıcı siteye girdiğinde anında expire
  • Cron olmasa bile çalışır!

Yedek Güvenlik: Cron Job

  • Günlük toplu temizlik
  • Siteye girmeyen kullanıcıları da temizle
  • Log tutma

💡 Böylece:

  • ✅ Cron çalışsa da çalışmasa da sistem güvenli!
  • ✅ Shared hosting'de sorunsuz!
  • ✅ Gerçek zamanlı expire!
  • ✅ Performans sounu yok!