9. Veritabanı ve Veri
DLE'nin veritabanı katmanı engine/classes/mysql.php içindeki db
sınıfıdır (366 satır). mysqli üzerine kuruludur ve MySQL 5.6.4 veya üstünü
gerektirir. Modüllerinizde bu nesne $db olarak hazırdır.
db sınıfının metotları
| Metot | Ne yapar? |
|---|---|
query($sql, $show_error = true, $log_query = true) | Sorgu çalıştırır, sonuç kaynağını döndürür. |
multi_query($sql, $show_error = true, $log_query = true) | Noktalı virgülle ayrılmış çoklu sorgu çalıştırır. |
super_query($sql, $multi = false, …) | Sorguyu çalıştırıp sonucu doğrudan döndürür. |
get_row($query_id = null) | Sonuçtan tek satır, yalnızca isimli indeksle. |
get_array($query_id = null) | Sonuçtan tek satır, hem isimli hem sayısal indeksle. |
num_rows($query_id = null) | Sonuçtaki satır sayısı. |
insert_id() | Son INSERT'in otomatik artan ID'si. |
get_affected_rows() | Etkilenen satır sayısı. |
safesql($source) | Metni SQL için kaçırır. Tek parametrelidir. |
free($query_id = null) | Sonuç belleğini serbest bırakır. |
close() | Bağlantıyı kapatır. |
get_result_fields() | Sonuç alanlarının bilgisi. |
get_real_time() | Mikrosaniyeli zaman (performans ölçümü). |
select(), insert(), update(), delete()
ve count() diye metotlar bulunmaz. Bu sınıf ham SQL çalıştırır;
soyutlama (ORM) katmanı yoktur. Ayrıca begin/commit/rollback gibi hazır bir
işlem (transaction) arayüzü de sunmaz.
super_query — en çok kullanacağınız metot
super_query($query, $multi = false, $show_error = true, $log_query = true)
$multi = false(varsayılan): tek satır ilişkisel dizi döner.$multi = true: satır dizisi döner (her satır ilişkisel dizi).
// Tek satır
$row = $db->super_query("SELECT COUNT(*) as count FROM " . PREFIX . "_post");
echo $row['count'];
// Birden çok satır
$rows = $db->super_query("SELECT id, title FROM " . PREFIX . "_post LIMIT 5", true);
foreach ($rows as $row) {
echo $row['title'];
}
Klasik döngü kalıbı
DLE'nin kendi modüllerinde en sık görülen kalıp query() + get_row()
döngüsü ve sonunda free()'dir:
$db->query("SELECT id, title FROM " . PREFIX . "_post ORDER BY id DESC LIMIT 10");
while ($row = $db->get_row()) {
$rows[] = $row;
}
$db->free();
Gerçek örnek — engine/modules/stats.php:
$db->query( "SHOW TABLE STATUS FROM `" . DBNAME . "`" );
while ( $r = $db->get_row() ) {
// …
}
$db->free();
num_rows() çağrısı free()'den önce yapılmalıdır;
çünkü free() sonucu yok eder ve query_id'yi null yapar.
get_row() ile get_array() farkı
| Altta kullanılan | Erişim | |
|---|---|---|
get_row() | mysqli_fetch_assoc | Yalnızca $row['title'] |
get_array() | mysqli_fetch_array | Hem $row['title'] hem $row[0] |
İkisi de tek satır döndürür; tüm sonucu değil. Çoğu durumda
get_row() tercih edilir çünkü bellek kullanımı daha azdır.
SQL güvenliği
"… WHERE id = '{$_GET['id']}'" gibi bir kullanım SQL enjeksiyonuna açıktır.
// Sayısal değerler: intval ile zorla
$id = intval($_GET['id']);
$db->query("SELECT * FROM " . PREFIX . "_post WHERE id = '{$id}'");
// Metin değerler: safesql ile kaçır
$name = $db->safesql($_POST['name']);
$db->query("SELECT * FROM " . PREFIX . "_benim_tablom WHERE baslik = '{$name}'");
safesql() tek parametre alır ve mysqli_real_escape_string
kullanır. Tablo/sütun adları için safesql() kullanmayın; onlar sabit olmalıdır.
PREFIX ve USERPREFIX
Tablo ön ekleri kurulumda engine/data/dbconfig.php içinde tanımlanır:
define ("PREFIX", "{$dbprefix}");
define ("USERPREFIX", "{$dbprefix}");
define ("COLLATE", "utf8mb4");
define('SECURE_AUTH_KEY', '{$auth_key}');
| Sabit | Nerede kullanılır? |
|---|---|
PREFIX | İçerik tabloları: _post, _comments, _category … |
USERPREFIX | Üye tabloları: _users, _usergroups, _banned … |
Varsayılan kurulumda ikisi aynı değere sahiptir, ama ayrı sabitlerdir. Doğru olanı kullanmak, ön eki farklı kurulumlarda da sorunsuz çalışmanızı sağlar.
Eklenti tablonuzu oluşturmak
Tabloyu manifestin mysqlinstall bloğunda oluşturun. SQL içinde
PREFIX kullanılmaz; onun yerine servis etiketi
{prefix} yazılır:
<mysqlinstall><![CDATA[
CREATE TABLE IF NOT EXISTS `{prefix}_benim_kutum` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`baslik` VARCHAR(255) NOT NULL DEFAULT '',
`sira` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `sira` (`sira`)
) ENGINE={engine} DEFAULT CHARSET={charset};
]]></mysqlinstall>
<mysqlupgrade><![CDATA[
-- Güncellemede SADECE tekrar çalıştırılabilir (idempotent) SQL yazın.
-- MySQL'de "ADD COLUMN IF NOT EXISTS" YOKTUR!
-- Kolon ekleme işini phpupgrade bloğuna bırakın (aşağıda).
CREATE TABLE IF NOT EXISTS `{prefix}_benim_kutum_log` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`mesaj` TEXT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE={engine} DEFAULT CHARSET={charset};
]]></mysqlupgrade>
<phpupgrade><![CDATA[
// Var olan tabloya kolon ekleme: önce var mı diye bak, yoksa ekle.
// (MySQL'de IF NOT EXISTS desteği olmadığı için tekrar çalıştırma güvenliği böyle sağlanır.)
$col = $db->super_query("SHOW COLUMNS FROM " . PREFIX . "_benim_kutum LIKE 'aktif'", false, false);
if (!$col) {
$db->query("ALTER TABLE " . PREFIX . "_benim_kutum ADD `aktif` TINYINT(1) NOT NULL DEFAULT '1'");
}
]]></phpupgrade>
<mysqldelete><![CDATA[
DROP TABLE IF EXISTS `{prefix}_benim_kutum`;
DROP TABLE IF EXISTS `{prefix}_benim_kutum_log`;
]]></mysqldelete>
| Servis etiketi | Yerine geçen |
|---|---|
{prefix} | PREFIX sabiti |
{userprefix} | USERPREFIX sabiti |
{charset} | COLLATE — temiz kurulumda utf8mb4 |
{engine} | InnoDB |
{prefix}_benim_kutum gibi. Ön eksiz bir tablo adı (benim_kutum)
başka eklentilerle çakışır ve DLE'nin yedek/geri yükleme araçlarınca bulunmaz.
Sessiz hata yakalama
query() metodunun ikinci parametresi $show_error'dır. Varsayılan
true iken bir SQL hatası sayfayı öldürür. false
verirseniz hata toplanır ve çalışma devam eder:
$db->query_errors_list = array();
$db->query("SELECT * FROM " . PREFIX . "_olmayan_tablo", false);
if (count($db->query_errors_list)) {
foreach ($db->query_errors_list as $err) {
// $err['query'] ve $err['error']
}
}
DLE, eklenti SQL bloklarını (mysqlinstall vb.) işte bu yöntemle çalıştırır ve
hataları _plugins_logs tablosuna type = 'mysql' olarak yazar.
Yani kendi SQL'inizde bir hata varsa Eklentiler → Hataları göster ekranında
görürsünüz.
Veritabanı kontrol listesi
- Tüm tablo adları
PREFIX(ya daUSERPREFIX) ile başlıyor. - Manifest SQL'inde
{prefix}/{engine}/{charset}kullanılmış. - Tablo
CREATE TABLE IF NOT EXISTSile kuruluyor. mysqlupgradebloğu da yazılmış (güncellemedemysqlinstallçalışmaz).mysqldeletetabloyu düşürüyor.- Metin girdileri
safesql(), sayısal girdilerintval()ile süzülüyor. - Döngü sonunda
$db->free()çağrılıyor. - Kurulum sonrası Hataları göster ekranı temiz.
Sırada: Ek Alanlar (xfields).