Php İle Nesne Yönelimli Yapıda Dinamik İndirim Kodu Doğrulama Sistemi Nasıl Yapılır?

Php İle Nesne Yönelimli Yapıda Dinamik İndirim Kodu Doğrulama Sistemi Nasıl Yapılır?
Php İle Nesne Yönelimli Yapıda Dinamik İndirim Kodu Doğrulama Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Sistemi geliştirmeye başlamadan önce PHP 8.3 veya daha güncel bir sürümün yüklü olduğundan emin olmalısınız. Ayrıca, veritabanı işlemleri için PDO (PHP Data Objects) kütüphanesini kullanacağız. PDO, SQL injection saldırılarına karşı hazırlıklı olmanızı sağlayan güvenli bir veritabanı erişim katmanıdır.

  • PHP 8.3+ (Tip güvenliği ve performans için güncel sürüm şarttır).
  • MySQL veya MariaDB veritabanı sunucusu.
  • Composer (Bağımlılık yönetimi için önerilir).
  • Temel düzeyde SQL bilgisi.

Veritabanı Yapısının Tasarlanması

Dinamik bir sistem için indirim kodlarını statik dosyalarda değil, veritabanında tutmalıyız. Kodların geçerlilik süresi, kullanım limiti ve indirim oranı gibi değişkenleri burada yönetiriz. Aşağıdaki SQL sorgusu, temel bir indirim tablosu oluşturmanızı sağlar.

CREATE TABLE discount_codes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    code VARCHAR(50) NOT NULL UNIQUE,
    discount_percent INT NOT NULL,
    expiry_date DATETIME NOT NULL,
    max_uses INT DEFAULT 1,
    current_uses INT DEFAULT 0,
    is_active BOOLEAN DEFAULT TRUE
);

Bu tablo yapısında code sütununu UNIQUE yaparak aynı kodun iki kez oluşturulmasını engelliyoruz. current_uses sütunu ise kodun kaç kez kullanıldığını takip etmemize olanak tanır.

İndirim Kodu Arayüzünü (Interface) Tanımlama

Nesne yönelimli programlamada (OOP), bir sınıfın hangi metotları içermesi gerektiğini belirlemek için arayüzler kullanırız. Bu, sistemin gelecekte farklı indirim türleri (örneğin: sabit tutarlı indirim veya kargo bedava) ile genişletilmesini kolaylaştırır.

interface DiscountStrategyInterface {
    public function validate(string $code): bool;
    public function applyDiscount(float $totalAmount): float;
}

Bu arayüz, her indirim türünün bir doğrulama (validate) ve bir indirim uygulama (applyDiscount) metoduna sahip olması gerektiğini garanti eder.

Dinamik Doğrulama Sınıfının Oluşturulması

Şimdi, veritabanı ile etkileşime girecek olan ana sınıfımızı yazalım. Bu sınıf, kodun veritabanında var olup olmadığını, süresinin dolup dolmadığını ve kullanım limitini kontrol eder.

class DiscountManager implements DiscountStrategyInterface {
    private PDO $db;

    public function __construct(PDO $db) {
        $this->db = $db;
    }

    public function validate(string $code): bool {
        $stmt = $this->db->prepare("SELECT * FROM discount_codes WHERE code = :code AND is_active = 1");
        $stmt->execute(['code' => $code]);
        $discount = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$discount) return false;

        // Süre kontrolü
        if (strtotime($discount['expiry_date']) < time()) return false;

        // Kullanım limiti kontrolü
        if ($discount['current_uses'] >= $discount['max_uses']) return false;

        return true;
    }

    public function applyDiscount(float $totalAmount): float {
        // İndirim hesaplama mantığı burada yer alacak
        return $totalAmount;
    }
}

Bu sınıf, bağımlılık enjeksiyonu (Dependency Injection) kullanarak veritabanı bağlantısını dışarıdan alır. Bu yöntem, birim testleri (unit testing) yaparken veritabanı bağlantısını kolayca taklit etmenize olanak tanır.

Güvenli Kod Uygulama ve Hata Yönetimi

Sistemin güvenliği için kullanıcıdan gelen veriyi asla doğrudan sorguya dahil etmemelisiniz. Yukarıdaki örnekte prepare ve execute metotları ile SQL injection riskini tamamen ortadan kaldırdık. Ancak, uygulama tarafında da bazı kontroller eklemeliyiz.

Güvenlik Uyarısı: İndirim kodu doğrulama sistemlerinde "Race Condition" (yarış durumu) riskine dikkat edilmelidir. Aynı anda iki kullanıcı son kullanım hakkını kullanmaya çalışırsa, current_uses değeri limiti aşabilir. Üretim ortamında veritabanı seviyesinde "Transaction" kullanmanız önerilir.

İndirim Hesaplama Mantığı ve Entegrasyon

Doğrulama başarılı olduktan sonra, indirim oranını uygulayan metodu geliştirelim. Bu metot, veritabanından aldığı yüzde değerini toplam tutardan düşer.

public function calculateDiscountedPrice(string $code, float $totalAmount): float {
    $stmt = $this->db->prepare("SELECT discount_percent FROM discount_codes WHERE code = :code");
    $stmt->execute(['code' => $code]);
    $percent = $stmt->fetchColumn();

    $discountAmount = $totalAmount * ($percent / 100);
    return $totalAmount - $discountAmount;
}

Bu metot, totalAmount değerini alır ve indirimli fiyatı döner. Böylece sepet toplamını bozmadan sadece indirimli tutarı hesaplamış olursunuz.

Karşılaştırma: Statik vs Dinamik Doğrulama

Özellik Statik (Hard-coded) Dinamik (OOP + DB)
Yönetim Kod değişikliği gerekir Admin paneli ile yönetilir
Güvenlik Zayıf Yüksek (PDO ile)
Esneklik Düşük Yüksek
Performans Çok Yüksek Yüksek (Cache ile desteklenmeli)

Sıkça Sorulan Sorular

İndirim kodlarını veritabanında saklamak performansı düşürür mü?

Doğrudan veritabanı sorgusu yapmak küçük ölçekli sitelerde sorun yaratmaz. Ancak yüksek trafikli sitelerde, Redis gibi bir önbellekleme (caching) mekanizması kullanarak kod bilgilerini bellekte tutmanız önerilir.

İndirim kodunun tek kullanımlık olduğunu nasıl garanti ederim?

Veritabanında max_uses değerini 1 olarak belirleyip, kod başarıyla kullanıldığında current_uses değerini bir artırarak ve is_active durumunu güncelleyerek garanti altına alabilirsiniz.

Farklı indirim türlerini nasıl eklerim?

DiscountStrategyInterface arayüzünü uygulayan yeni sınıflar (örneğin FixedAmountDiscount) oluşturarak sisteminize esneklik katabilirsiniz.

Kullanıcı indirim kodunu yanlış girerse ne yapmalıyım?

Sisteminize hata yönetimi ekleyerek, validate metodu false döndüğünde kullanıcıya "Geçersiz veya süresi dolmuş kod" şeklinde net bir geri bildirim vermelisiniz.

Bu sistemi Laravel gibi frameworklerde kullanabilir miyim?

Elbette. Bu mantık, Laravel'in Service Container ve Eloquent ORM yapısına çok kolay entegre edilebilir. Sadece PDO yerine Laravel'in Query Builder veya Eloquent model yapılarını kullanmanız yeterlidir.

Sorumluluk Reddi: Bu kod örnekleri eğitim amaçlıdır. Üretim ortamına almadan önce mutlaka kapsamlı testlerden geçirin, giriş verilerini doğrulayın (validation) ve sanitizasyon işlemlerini ihmal etmeyin.

İleri Seviye İpucu: Redis ile Önbellekleme Stratejisi

Veritabanı sorguları, özellikle yüksek trafikli e-ticaret sitelerinde darboğaz oluşturabilir. İndirim kodlarının doğrulanması sırasında her seferinde SQL sorgusu çalıştırmak yerine, Redis gibi bir anahtar-değer (key-value) deposu kullanarak sistemin performansını ciddi oranda artırabilirsiniz. Kod doğrulama işlemini bellekte gerçekleştirmek, yanıt süresini milisaniyeler seviyesine çeker.

Aşağıdaki örnekte, indirim kodunun Redis üzerinde nasıl kontrol edileceğini ve veritabanı ile nasıl senkronize edileceğini görebilirsiniz:


class RedisDiscountService {
    private $redis;
    private $db;

    public function __construct($redis, $db) {
        $this->redis = $redis;
        $this->db = $db;
    }

    public function validate($code) {
        // Önce Redis'te ara
        if ($this->redis->exists($code)) {
            return json_decode($this->redis->get($code), true);
        }

        // Redis'te yoksa veritabanından getir
        $discount = $this->db->table('discounts')->where('code', $code)->first();

        if ($discount) {
            // Gelecek sorgular için Redis'e kaydet (1 saat geçerli)
            $this->redis->setex($code, 3600, json_encode($discount));
        }

        return $discount;
    }
}

Sistem Testleri ve Hata Ayıklama (Debugging)

Dinamik bir indirim sistemi kurarken, kodun farklı senaryolarda nasıl tepki verdiğini doğrulamak için birim testleri (Unit Testing) yazmak kritiktir. Özellikle "geçerlilik tarihi geçmiş kodlar", "limitine ulaşmış kodlar" ve "geçersiz karakter içeren girdiler" gibi durumlar için test senaryoları oluşturmalısınız.

Test Senaryosu Tablosu

Senaryo Beklenen Sonuç Hata Kodu
Geçerli Kod İndirim Uygulanır 200
Süresi Dolmuş Kod Hata: Kodun süresi doldu 403
Limit Aşımı Hata: Kullanım limiti doldu 422
Veritabanında Olmayan Kod Hata: Kod bulunamadı 404

Hata ayıklama sürecinde, uygulamanızın log mekanizmasını aktif tutarak hangi kodun hangi kullanıcı tarafından ne zaman denendiğini takip etmeniz, olası bir suistimali (brute-force denemeleri) erkenden fark etmenizi sağlar. PHP'nin error_log() fonksiyonunu veya Monolog gibi kütüphaneleri kullanarak her başarısız denemeyi kayıt altına almalısınız.


try {
    $result = $discountService->apply($userCode);
} catch (InvalidCodeException $e) {
    error_log("Geçersiz kod denemesi: " . $userCode . " - Hata: " . $e->getMessage());
    return response()->json(['error' => 'Geçersiz kod'], 400);
}

Bu yaklaşım, sisteminizin sadece çalışır durumda kalmasını değil, aynı zamanda güvenli ve izlenebilir olmasını da garanti eder. Özellikle büyük ölçekli projelerde, bu tür hata ayıklama katmanları sistemin sürdürülebilirliği için vazgeçilmezdir.

Sonuç

PHP ile nesne yönelimli yapıda dinamik bir indirim kodu sistemi kurmak, projenizin profesyonelliğini bir üst seviyeye taşır. Arayüzler ve veritabanı etkileşimi ile kurduğunuz bu yapı, gelecekteki geliştirmeleriniz için sağlam bir temel oluşturacaktır. Bir sonraki adım olarak, bu sisteme bir "Kullanıcı Bazlı İndirim" özelliği ekleyerek, belirli kullanıcıların sadece kendilerine tanımlanan kodları kullanabilmesini sağlayabilirsiniz.

Bu yazıya tepkinizi paylaşın:
Mert Çelik

Hobi ve teknik beceriler üzerine eğitici içerikler kurguluyorum. Okuyucuların günlük hayatta karşılaştığı sorunlara uygulanabilir çözümler sunmayı hedefliyorum.

Yorumlar (0)

Yorum Yaz