tarihinde yayınlandı Yorum yapın

MySQL Kullanılan Projede ‘schema:dump –prune’ Sonrasında Test’lerin SQLite İle Çalışmaması

Merhaba arkadaşlar,

Bugün Laravel ile geliştirdiğim backend api servisinde ilginç bir durum ile karşılaştım. Bu hatayı tanımlamam gerekirse:

  • Üzerinde çalıştığım projede yüzlerce migration dosyası oluşmaya başladı. Her yeni migration oluşturduğumda database dizini altında yeni oluşturduğum migration dosyasına kaydırmaktan iyice bıkkınlık gelmişti.
  • Bunun için buradan görebileceğiniz üzere migrationları silip bir dump dosyası oluşturdum. Projemde MySQL kullanıyorum.
Bash
# Mevcut veritabanının bir dumpını oluşturur ve migration'ların hepsini temizler.
php artisan schema:dump --prune
  • Bu işlem sonrası migrations dizini uçuyor ve yerime schema isimli yeni bir dizin geliyor. İçerisinde de mysql kullandığım için mysql-schema.sql isimli bir dosya oluşuyor. Buraya kadar her şey harika.

Buraya kadar her şey güzel. Artık daha sade ve temiz bir database dizinim var. Fakat problem testlerimin çalışmasında başlıyor. Testlerimde her zaman veritabanını sıfırlıyorum:

PHP
<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

Evet, ben de Pest kullanıyorum. Test içinse veritabanı olarak olarak SQLite kullanıyorum. Bağlantımda :memory: olarak ayarlı. Problem burada başlıyor. Migration’larımızı sildiğimiz için ve veritabanı dumpımız mysql olduğu sqlite ile veritabanı oluşturulamıyor. Test sonuçlarımda düzenli olarak users tablosu bulunamadı hatası alıyorum. Ufak bir çakallık deneyip mysql-schema.sql dosyamın adını sqlite-schema.sql olarak değiştirsem yedirir miyim diye bir düşündüm, düşükte olsa umut fakirin ekmeğiydi ama tabii ki olmadı 🙂

Bunun için çözümler üretmeye çalışırken mysql dump dosyasını sqlite dumpa dönüştürmek aklıma geldi. Bunun için github’da dumblob/mysql2sqlite reposunu keşfettim. Bu toolu kullanarak mevcut mysql dumpımdan sqlite dump oluşturdum. Bu repodan mysql2sqlite dosyasını projemin ana dizininde oluşturdum ve sonrasında şu komutu çalıştırdım:

Bash
./mysql2sqlite database/schema/mysql-schema.sql > database/schema/sqlite-schema.sql

Voila! sqlite-schema.sql dosyam schema klasörünün altında oluşmuştu. Tabii şimdi test etmeye geldi.

Bash
php artisan test

Artık sağlıklı bir şekilde sqlite-schema.sql dosyasını sağlıklı bir şekilde kullanarak veritabanımı sıfırlayabiliyorum.

Umarım birinize ilaç olabilecek bir yaklaşım sunmuşumdur. Bu yazıyı yazarken neden şu konuları da açıklamam gerektiğini hissettim, bir ara bunlara da değineceğim, kendime not olması açısından:

  • Test nedir? PHPUnit ve Pest nedir?
  • Neden test yazmalıyız?
  • Neden testlerimizde sqlite kullanmalıyız ya da kullanmak zorunda mıyız?

Ölmez sağ kalır isek bir ara yazarız 🙂 Kalın sağlıcakla.

tarihinde yayınlandı Yorum yapın

Laravel’da Foreign Key’ler İçeren Bileşik İndeksler Nasıl Kaldırılır?

Bir Laravel geliştiricisi olarak, veritabanı tabloları arasındaki ilişkileri yönetirken foreign key’ler ve indekslerle sıklıkla karşılaşıyoruzdur. Ancak, bileşik bir indeks oluştururken foreign key’leri içermesi durumunda bazı zorluklar yaşanabilir. Bu yazıda, Laravel’da foreign key’ler içeren bir bileşik indeksi nasıl kaldıracağımızı göreceğiz.

Bileşik indeksler birden çok kolonda oluşturulan indekslerdir ve genellikle veritabanı sorgularının performansını artırmak için kullanılırlar. Bununla birlikte, foreign key’lerle birlikte kullanıldıklarında bazen karışık durumlar ortaya çıkabilir.

Örneğin, contact_tags adlı bir tablomuz olsun ve bu tabloda tag_id ve contact_id adında iki foreign key’imiz olsun. Bu iki sütunu içeren bir bileşik indeks oluşturduk (tag_contact_unique adlı). Ancak, bu indeksi kaldırmak istediğimizde bir problemle karşılaşıyoruz.

İşte bu problemi çözmenin bir yolunu aşağıda bulabilirsiniz:

PHP
public function down() {
    Schema::table('contact_tags', function (Blueprint $table) {
        // Bu biraz garip gelebilir, ancak öncelikle eksik indeksleri eklememiz gerekiyor:
        $table->index('tag_id', 'tag_id_foreign');
        $table->index('contact_id', 'contact_id_foreign');
        // Şimdi bu "down" komutunun ana kısmına geçerek benzersiz indeksi kaldırabiliriz:
        $table->dropUnique('tag_contact_unique');
    });
}

Bu kodda neler olduğuna bir göz atalım:

  1. Öncelikle, tag_id ve contact_id sütunlarına indeks ekliyoruz. Burada dikkat edilmesi gereken önemli nokta, indeks isimlerinin foreign key isimleriyle aynı olması gerektiğidir. Bu, Laravel’in foreign key’leri ve indeksleri birbirinden ayırt etmesine yardımcı olur.
  2. Ardından, tag_contact_unique adındaki bileşik indeksi kaldırıyoruz. Bu, tag_id ve contact_id sütunlarında oluşturduğumuz benzersiz bileşik indeksi kaldırır.

Sonuç olarak, foreign key’ler içeren bir bileşik indeksi kaldırmak için bu yöntemi kullanabiliriz.