Kategoriler
Phalcon Yazılımcılar İçin Hayatta Kalma Kılavuzu

Phalcon’da Karşılaştığım İki Can Sıkıcı Hata ve Çözümleri: e_id ve SoftDelete

Eğer Phalcon kullanıyorsan, muhtemelen performans ve esneklik açısından ne kadar güçlü olduğunu fark etmişsindir. Ama işte, her güzel şeyin bir bedeli var! Phalcon’un PHQL (Phalcon Query Language) motoru bazen beklenmedik sürprizler yapabiliyor.

Phalcon’da Neler Ters Gidiyor?

Ben de iki can sıkıcı sorunla karşılaştım:

  1. e_id Hatası: note_id gibi masum bir sütun adını sorguya yazdığında, Phalcon’un bunu not e_id gibi ayrıştırıp “Column ‘e_id’ doesn’t exist” hatası vermesi.
  2. SoftDelete ile Kalıcı Silme Sorunu: SoftDelete davranışını kullanıyorsun, ama bazen kayıtları gerçekten veritabanından silmen gerekiyor. Phalcon, modeli initialize edip önbelleğe aldığı için bu davranışı çalışma anında atlamak neredeyse imkânsız.

Bu sorunlar seni de çıldırttı mı? Hadi, çözümleri konuşalım!

Neden Bu Kadar Sinir Bozucu?

e_id Hatası

Diyelim ki NotesTranslations modelinde bir sorgu çalıştırıyorsun:

$translation = NotesTranslations::findFirst([
    'conditions' => 'note_id = :noteId:',
    'bind' => ['noteId' => 123]
]);

Ve BAM! Karşında şu hata:
Column 'e_id' doesn't belong to any of the selected models.
Neden? Çünkü Phalcon’un PHQL motoru, note_id’yi ayrıştırırken not ifadesini bir operatör sanıyor ve e_id’yi bir sütun gibi algılıyor. Tabii ki veritabanında böyle bir sütun yok! Saatlerce debug yap, stack trace’leri tara, ama çözüm internette bile zor bulunuyor. Bu hata, özellikle sütun adlarında not gibi kelimeler geçtiğinde seni çaresiz bırakabilir.

SoftDelete Sorunu

SoftDelete davranışıyla çalışırken, is_deleted gibi bir sütunu güncelleyerek kayıtları “silmiş” gibi yapıyorsun. Ama bazen, mesela bir test ortamında veya yasal bir gereklilik yüzünden, kayıtları gerçekten silmen gerekiyor. Phalcon’un modelsManager’ı, modeli ilk sorguda initialize edip önbelleğe alıyor. Bu yüzden SoftDelete’i çalışma anında devre dışı bırakmak mümkün değil. Ne denesen olmuyor:

  • Statik bir bayrak ($disableSoftDelete) ekliyorsun, ama model zaten önbelleğe alınmış.
  • Çocuk sınıf oluşturuyorsun, ama Phalcon yine ana sınıfı kullanıyor.
  • PHQL ile ham sorgu yazıyorsun, ama yine modelin davranışları devreye giriyor.

Bu durum, projenin ortasında saatlerini yiyebilir ve seni “Neden Phalcon kullanıyorum ki?” diye sorgulamaya itebilir.

İşte Çözümler!

1. e_id Hatasını Çözme

e_id hatasının çözümü basit ama kurnazca: PHQL sorgularında sütun adlarını köşeli parantez ([]) ile sar! Bu, Phalcon’un sütun adını yanlış ayrıştırmasını önler. Örneğin:

$translation = NotesTranslations::findFirst([
    'conditions' => '[note_id] = :noteId: AND [language_id] = :languageId:',
    'bind' => [
        'noteId' => 123,
        'languageId' => 1
    ]
]);

Bu küçük değişiklik, Phalcon’un note_id’yi not e_id gibi görmesini engeller. Artık hata yok, sorgu düzgün çalışıyor! Ama dikkat: Bu sadece PHQL sorguları için geçerli. PDO ile ham SQL yazarsan, köşeli parantezlere gerek kalmaz.

İpucu: Eğer sütun adlarında not gibi başka potansiyel tuzaklar varsa (örneğin, order_id veya set_id), her zaman [sütun_adı] formatını kullan. Böylece Phalcon’un PHQL motorunu kandırmış olursun!

2. SoftDelete ile Kalıcı Silme

SoftDelete davranışını atlayarak kalıcı silme yapmak için en kesin çözüm, Phalcon’un model katmanını tamamen bypass edip PDO ile ham SQL sorguları kullanmak. Neden? Çünkü PHQL, modeli initialize eder ve SoftDelete davranışını devre dışı bırakamazsın. İşte adım adım çözüm:

Adım 1: PDO ile Ham SQL

Notes modelinde kalıcı silme için bir deletePermanently metodu yazalım:

public function deletePermanently()
{
    $messages = [];
    $db = $this->getDI()->getDb(); // PDO bağlantısını al

    try {
        $sql = "DELETE FROM notes WHERE id = :id";
        $stmt = $db->prepare($sql);
        $stmt->execute(['id' => $this->id]);
        error_log("Deleted {$stmt->rowCount()} rows from notes for id = {$this->id}");

        return [true, $messages];
    } catch (\PDOException $e) {
        $messages[] = "Database error: {$e->getMessage()}";
        error_log("Error in deletePermanently: {$e->getMessage()}");
        return [false, $messages];
    }
}

Adım 2: Controller’da Kullanım

NotesController’da bu metodu çağıran bir action yazalım:

public function deletePermanentlyAction()
{
    $json = $this->request->getJsonRawBody();

    if (!isset($json->noteId)) {
        return $this->response->setJsonContent([
            'status' => 'error',
            'success' => false,
            'error' => 'Note ID is required',
            'data' => []
        ]);
    }

    $note = Notes::findFirst([
        'conditions' => '[id] = :id:',
        'bind' => ['id' => (int)$json->noteId]
    ]);

    if (!$note) {
        return $this->response->setJsonContent([
            'status' => 'error',
            'success' => false,
            'error' => 'Note not found',
            'data' => []
        ]);
    }

    try {
        [$success, $messages] = $note->deletePermanently();
        if (!$success) {
            return $this->response->setJsonContent([
                'status' => 'error',
                'success' => false,
                'error' => $messages ?: ['Failed to delete permanently'],
                'data' => []
            ]);
        }
    } catch (\Exception $e) {
        return $this->response->setJsonContent([
            'status' => 'error',
            'success' => false,
            'error' => $e->getMessage(),
            'data' => []
        ]);
    }

    return $this->response->setJsonContent([
        'status' => 'success',
        'success' => true,
        'error' => null,
        'data' => []
    ]);
}

Adım 3: Hata Ayıklama

Eğer silme işlemi başarısız olursa, veritabanı kısıtlamalarını kontrol et. Örneğin:

SHOW CREATE TABLE notes_translations;

Foreign key varsa ve ON DELETE CASCADE tanımlı değilse, yukarıdaki kod zaten ilişkili kayıtları önce siliyor.

İpucu: Loglama ekle! Her silme işlemi sonrası etkilenen satır sayısını ($stmt->rowCount()) logla. Böylece hangi tablodan kaç kayıt silindiğini görebilirsin.

Son Söz

Phalcon güçlü bir framework, ama bu tür tuzaklar her geliştiricinin başına gelebilir. e_id hatasını [note_id] ile çözmek ve SoftDelete’i PDO ile atlamak, saatlerce debug yapmaktan kurtarır. Umarım bu çözümler senin de projelerinde işini kolaylaştırır! Başka bir Phalcon maceranda takılırsan, bloguma göz at veya bana yaz, birlikte çözeriz!

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir