PHP PDO Ajax CRUD Örneği

DataTables, Bootstrap 5 ve modal pencerelerle çalışan, satır satır açıklamalı bir CRUD örneği. SQL enjeksiyonu, XSS ve dosya yükleme açıkları baştan kapatılmış.

PHP 8 PDO MySQL Ajax DataTables Bootstrap 5
Seviye
Başlangıç
Dosya
34
Kod satırı
~27.374
Proje boyutu
2.3 MB
Veritabanı
crud
Lisans
MIT
İnceleme
0
Beğeni
0
Yayın

Ekran Görüntüleri 4 görsel

Bu Örnek Ne Yapıyor?

  • Tam CRUD: listeleme, ekleme, düzenleme, silme ve görsel yükleme
  • Sunucu taraflı DataTables ile arama, sıralama ve sayfalama
  • Bootstrap 5 modalları: tek modal hem ekleme hem düzenleme için kullanılıyor
  • Sorgular hazırlanmış ifadelerle (prepared statement) çalışıyor — SQL enjeksiyonu kapalı
  • Çıktı kaçışlama ile XSS, içerikten tür doğrulama ile dosya yükleme açığı kapatılmış
  • Görseli olmayan kayıtlar için adın baş harfinden otomatik rozet üretiliyor
  • Kodun her satırı Türkçe açıklamalı; Composer, npm ve internet bağlantısı gerekmiyor

Nerede İşe Yarar?

  • PHP, Ajax ve DataTables üçlüsünü sıfırdan öğrenmek
  • Yeni bir projeye hazır ve güvenli bir CRUD iskeletiyle başlamak
  • Müşteri, personel veya ürün listesi gibi klasik yönetim ekranları
  • Var olan bir CRUD kodunu güvenlik açısından karşılaştırmak
  • Bootstrap 5 üzerine kurulu, tekrar kullanılabilir bir tasarım kalıbı edinmek

Gereksinimler

  • PHP 8.0+ (pdo_mysql, gd) · MySQL 5.7+ veya MariaDB 10.3+ · Apache/mod_rewrite

Nasıl Kurulur?

  1. Proje dosyalarını web köküne kopyalayın (örn. XAMPP'ta htdocs veya kendi web sunucunuzun kök dizini)
  2. crud.sql dosyasını içe aktarın — tabloyu ve örnek kayıtları oluşturur
  3. system klasöründeki yapılandırma dosyasında veritabanı bilgilerini düzenleyin
  4. upload klasörüne yazma izni verin (kayıt görselleri buraya kaydedilir)
  5. Uygulamayı açın; listeye bir kayıt ekleyip modal üzerinden düzenlemeyi deneyin

Veritabanı şeması projedeki crud.sql dosyasında.

Nasıl Çalışıyor?

PHP PDO MySQL Ajax CRUD

DataTables · Bootstrap 5 · Modal · Çılgın Yazılım Tasarım Kalıbı

Güvenli, açıklamalı ve indirir indirmez çalışan bir CRUD örneği.

PHP
MySQL
Bootstrap
DataTables
License

🇹🇷 Türkçe  ·  🇬🇧 English

cilginyazilim.com



Bu Proje Nedir?


PHP öğrenirken bulunan CRUD örneklerinin çoğu SQL injection, XSS ve dosya yükleme açıkları içerir. Bu proje, aynı işi doğru ve güvenli yapmanın nasıl göründüğünü göstermek için hazırlandı.

Öne çıkan yanı: kodun her satırı açıklamalı. Bir şeyin neden öyle yazıldığını, yanlış yazılsa ne olacağını yorum satırlarında bulacaksınız. PHP'ye yeni başlayan biri bile dosyaları okuyarak neyin ne işe yaradığını kavrayabilir.

Kimler için uygun?

  • PHP + AJAX + DataTables üçlüsünü öğrenmek isteyenler
  • Kendi projesine hazır ve güvenli bir CRUD iskeleti arayanlar
  • Bootstrap 5 üzerine kurulu, tekrar kullanılabilir bir tasarım kalıbı arayanlar
Klonla, crud.sql'i içe aktar, çalıştır. Başka hiçbir kurulum adımı yok. Composer yok, npm yok, internet bağlantısı bile gerekmiyor — tüm kütüphaneler proje içinde.

İçindekiler


Ekran Görüntüleri

Kayıt listesi

Gradyanlı marka başlığı, canlı arama, sıralanabilir sütunlar ve tek sütunda toplanmış işlem butonları. Görseli olmayan kayıtlar için adın baş harfinden otomatik rozet üretilir.

Kayıt listesi

Detay modalı

Göz butonuna basıldığında açılır. Büyük profil görseli, kayıt bilgileri ve düzenlemeye geçiş kısayolu içerir.

Detay modalı

Ekleme / düzenleme formu

Tek bir modal hem ekleme hem düzenleme için kullanılır. Görsel seçildiğinde canlı önizleme gösterilir, hatalar ilgili alanın altında belirir.

Form modalı

Sunucu taraflı sayfalama

Sayfalama, arama ve sıralama sunucuda yapılır; tarayıcıya yalnızca görüntülenen sayfa gönderilir.

Sayfalama

Arama

Ad ve soyad üzerinde arama yapılır. recordsFiltered doğru hesaplandığı için sayfalama filtreye uyum sağlar.

Arama

Üç modal:

ModalAçılışİçerik
👁 DetayGöz butonuBüyük profil görseli, kayıt no, ad, soyad, dosya adı, tarih + "Bu Kaydı Düzenle" kısayolu
Ekle / DüzenleYeni Kayıt veya kalem butonuForm, canlı görsel önizleme, alan bazlı hata mesajları
🗑 SilÇöp kutusu butonuKimin silineceğini yazan onay ekranı

Neler Var?

Arayüz
  • Marka gradyanlı başlık ve modallar
  • Üç ayrı modal (detay / form / silme onayı)
  • Sağ üstte toast bildirimleri
  • Görsel canlı önizleme (yüklemeden önce)
  • Görselsiz kayıtlar için baş harf rozeti
  • Otomatik koyu tema (işletim sistemi ayarını izler)
  • Mobil uyumlu, erişilebilir (ARIA etiketli)
  • Tamamı Türkçe — CDN'siz, çevrimdışı çalışır

Altyapı

  • Sunucu taraflı (server-side) DataTables
  • Tek AJAX uç noktası, action tabanlı yönlendirme
  • Çift katmanlı doğrulama (istemci + sunucu)
  • Alan bazlı hata mesajları (HTTP 422)
  • Otomatik dosya temizliği (yetim dosya bırakmaz)
  • Ortam değişkeni desteği
  • 50 hazır örnek kayıt
  • Kodun her satırı açıklamalı



Güvenlik: Neyi, Nasıl Kapattık?


İnternetteki benzer örneklerin çoğunda bulunan açıklar ve bu projede nasıl önlendikleri:

AçıkTipik hatalı kodBu projede
SQL Injection"SELECT FROM users WHERE id = '".$_POST['id']."'"Tüm sorgular prepared statement. EMULATE_PREPARES = false ile gerçek prepared statement zorunlu. Sıralama sütunu/yönü beyaz listeden geçer — order[0][column]=0;DROP TABLE users-- denemesi test edildi, etkisiz.
XSS$sub_array[] = $row["name"];Veritabanından gelen her değer e() (htmlspecialchars) ile kaçışlanır. Toast mesajları .text() ile yazılır, .html() ile değil.
CSRF(genelde hiç yok)Oturuma bağlı 32 baytlık token. ` etiketinden okunup her AJAX isteğine eklenir, hash_equals() ile sabit zamanlı doğrulanır. Token'sız istek → HTTP 419.
Kötü amaçlı dosya yükleme$ext = explode('.', $name)[1];Uzantıya güvenilmez: tür getimagesize() ile dosya içeriğinden tespit edilir. Yeni ad random_bytes() ile üretilir, uzantı MIME beyaz listesinden atanır. shell.php.png yükleme denemesi test edildi, reddedildi.
Yükleme klasöründe kod çalıştırma(korumasız klasör)*upload/.htaccess PHP motorunu kapatır ve çalıştırılabilir uzantılara erişimi engeller.
Path Traversalunlink("../upload/".$_POST['hidden_image'])Silinecek dosya adı istemciden değil veritabanından okunur, ayrıca basename() ile temizlenir.
Tip karmaşasıWHERE id = '$id'ID'ler filter_input(..., FILTER_VALIDATE_INT) ile doğrulanır.
Bilgi sızıntısıEkrana basılan MySQL hatalarıAPP_DEBUG = false iken hata detayı gizlenir, error_log()'a yazılır.
LIKE joker karakterleriLIKE '%$search%'Arama terimindeki %, _, \ kaçışlanır — kullanıcı % yazınca tüm tablo dönmez.
Kaynak tüketimiLIMIT $lengthSayfa boyutu 500 ile sınırlanır; length=999999` sunucuyu yormaz.

Kurulum

Gereksinimler

  • PHP 8.0+ (pdo_mysql ve gd eklentileri)
  • MySQL 5.7+ veya MariaDB 10.3+
  • Apache (XAMPP / WAMP / Laragon) — ya da PHP'nin yerleşik sunucusu

Adımlar

1 — Projeyi indirin

git clone https://github.com/CilginYazilim/PHP-PDO-MySQL-Ajax-CRUD-DataTables-Bootstrap-5-Modals.git
cd PHP-PDO-MySQL-Ajax-CRUD-DataTables-Bootstrap-5-Modals

2 — Veritabanını oluşturun

crud.sql veritabanını da kendisi oluşturur; önceden crud adında bir veritabanı açmanıza gerek yok.

mysql -u root -p < crud.sql

phpMyAdmin ile: İçe Aktar → Dosya seç → crud.sql → Başlat

3 — Çalıştırın

php -S 127.0.0.1:8000

XAMPP kullanıyorsanız projeyi htdocs altına koymanız ve şu adresi açmanız yeterli:
http://localhost/PHP-PDO-MySQL-Ajax-CRUD-DataTables-Bootstrap-5-Modals/

4 — Tarayıcıda açınhttp://127.0.0.1:8000/

Karşınıza 50 örnek kayıt dolu, çalışır durumda bir tablo gelecek.

Linux/macOS kullanıcıları: upload/ klasörüne yazma izni gerekir → chmod 755 upload

Yapılandırma

Tüm ayarlar system/config.php içinde, açıklamalarıyla birlikte:
SabitVarsayılanAçıklama
DB_HOST127.0.0.1Veritabanı sunucusu
DB_NAMEcrudVeritabanı adı
DB_USERrootKullanıcı adı
DB_PASS(boş)Parola
UPLOAD_MAX_BYTES2 MBMaksimum görsel boyutu
ALLOWED_IMAGE_TYPESjpg, png, gif, webpİzin verilen MIME türleri
NAME_MIN_LENGTH / NAME_MAX_LENGTH2 / 150Ad-soyad uzunluk sınırları
APP_DEBUGtrueCanlıda false yapın

Şifreyi koda yazmayın

Tüm DB_* sabitleri ortam değişkeniyle geçersiz kılınabilir. Böylece şifreniz GitHub'a düşmez:

# Linux / macOS
export DB_HOST=localhost DB_USER=uygulama DB_PASS='guclu-sifre'

# Windows (PowerShell)
$env:DB_USER = "uygulama"; $env:DB_PASS = "guclu-sifre"

Apache için .htaccess ya da httpd.conf içinde: SetEnv DB_PASS "guclu-sifre"


Çılgın Yazılım Tasarım Kalıbı


assets/css/cilginyazilim.css dosyası, bu projeye değil markaya aittir. Diğer örnek projelerde de aynı görsel dili kullanabilmek için ayrı bir dosya olarak tutulur.

Başka bir projede kullanmak

<!-- 1) Bootstrap'ten SONRA ekleyin -->
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/cilginyazilim.css">

<!-- 2) body'ye tema sınıfını verin -->
<body class="cy-app">

Hazır bileşenler

SınıfNe işe yarar
.cy-card / .cy-card__header / .cy-card__body / .cy-card__footerGradyan başlıklı ana kart
.cy-brand / .cy-brand__markLogo kutusu + başlık bloğu
.cy-btn + .cy-btn--primary \--onbrandMarka butonları
.cy-btn-icon + --view \--edit \--deleteTablo içi ikon butonları
.cy-tableMarka görünümlü tablo
.cy-avatar / .cy-avatar--initial / .cy-avatar--lgProfil görseli ve baş harf rozeti
.cy-badge + --glass \--softRozetler
.cy-modalGradyan başlıklı modal
.cy-detailEtiket/değer listesi (detay modalı)
.cy-toast + --success \--danger \--infoBildirim balonları

Renkleri değiştirmek

Tüm bileşenler CSS değişkenlerinden beslenir. Tek yeri değiştirmek yeter:

:root {
    --cy-brand-900: #061321;   /* Logodaki en koyu lacivert */
    --cy-brand-600: #0b5cb5;   /* Ana marka mavisi          */
    --cy-accent:    #0ea5e9;   /* Vurgu rengi               */
    --cy-gradient:  linear-gradient(135deg, #061321, #0b5cb5 45%, #0284c7);
}

Renk paleti cilginyazilim.com logosundan türetilmiştir: koyu lacivertten canlı maviye uzanan geçiş. Logo assets/images/logo.png içinde yer alır ve başlıkta beyaz yuvarlak bir zemine oturtulur.

Koyu tema

Kullanıcının işletim sistemi koyu temadaysa otomatik devreye girer. Zorlamak isterseniz:

<html data-cy-theme="dark">   <!-- veya "light" -->



Dosya Yapısı


.
├── index.php                      # Arayüz + tüm JavaScript mantığı
├── crud.sql                       # Veritabanı şeması + 50 örnek kayıt
├── README.md                      # Türkçe belgelendirme
├── README.en.md                   # İngilizce belgelendirme
├── LICENSE                        # MIT lisansı
├── .gitignore
│
├── docs/
│   └── screenshots/               # README'de kullanılan ekran görüntüleri
│
├── system/
│   ├── config.php                 # Ayarlar, oturum, PDO bağlantısı
│   ├── function.php               # Yardımcı fonksiyonlar
│   └── ajax.php                   # AJAX uç noktası / CRUD yönlendiricisi
│
├── assets/
│   ├── css/
│   │   ├── bootstrap.min.css
│   │   ├── dataTables.bootstrap5.min.css
│   │   ├── cilginyazilim.css      # ★ MARKA TASARIM KALIBI
│   │   └── style.css              # Sadece bu sayfaya özel eklemeler
│   └── js/
│       ├── jquery-3.7.0.js
│       ├── bootstrap.bundle.js
│       ├── jquery.dataTables.min.js
│       └── dataTables.bootstrap5.min.js
│
└── upload/
    ├── .htaccess                  # Klasörde kod çalıştırmayı engeller
    └── *.png                      # Örnek görseller

Yükleme sırası önemlidir:

CSS:  bootstrap → dataTables → cilginyazilim → style
JS:   jQuery → bootstrap.bundle → dataTables → dataTables.bootstrap5

Sıra bozulursa $ is not defined gibi hatalar alırsınız.


Nasıl Çalışıyor?


┌─────────────────────────────────────────────────────────────────────┐
│  TARAYICI  (index.php)                                              │
│                                                                      │
│  DataTables ──┐                                                      │
│  Form gönder ─┤                                                      │
│  Detay butonu ┼──► jQuery AJAX ──► POST { action, csrf_token, ... }  │
│  Sil butonu ──┘                              │                       │
└──────────────────────────────────────────────┼───────────────────────┘
                                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│  SUNUCU  (system/ajax.php)                                          │
│                                                                      │
│   1. POST mu?              → değilse 405                            │
│   2. require_csrf()        → geçersizse 419                         │
│   3. action'a göre dağıt:  list │ add │ edit │ fetch │ delete       │
│   4. validate_name()       → hatalıysa 422 + errors                 │
│   5. upload_image()        → içerikten tür doğrulama                │
│   6. PDO prepared query    → MySQL                                  │
│   7. json_response()       → tek noktadan JSON çıkışı               │
│                                                                      │
│   Tüm bunlar try/catch içinde: hiçbir hata çıplak PHP mesajı olarak │
│   sızmaz, hepsi düzgün JSON'a çevrilir.                             │
└─────────────────────────────────────────────────────────────────────┘

Sorumluluk dağılımı


DosyaGörevi
index.phpSadece sunum. CSRF token üretir, DataTables'ı kurar, modalları ve toast'ları yönetir. Veritabanına dokunmaz.
system/ajax.phpYönlendirici. action değerine göre işleyicilere dağıtır. Tüm güvenlik kontrolleri ve hata yakalama burada tek noktada.
system/function.phpSaf yardımcı fonksiyonlar. Veritabanına ihtiyaç duyanlar PDO'yu parametre olarak alır — her çağrıda yeni bağlantı açılmaz.
system/config.phpOturum, sabitler ve tek bir PDO örneği.

Öğrenirken dikkat çeken noktalar

Kod içindeki yorumlarda ayrıntısıyla anlatılan, yeni başlayanların sık takıldığı konular:
  • serverSide: true ne demek? — 50 kayıtta fark etmez ama 100.000 kayıtta tarayıcıya tüm veriyi göndermemenizi sağlar.
  • Event delegation — AJAX ile sonradan gelen butonlara neden $('.js-edit').click() çalışmaz, $('#user_data').on('click', '.js-edit', ...) neden çalışır.
  • EMULATE_PREPARES = false tuzağı — aynı isimli yer tutucu (:search) neden iki kez kullanılamaz, Invalid parameter number hatası nereden gelir.
  • contentType: false, processData: false — dosya yüklerken bu ikisi neden zorunlu.
  • Sütun adı neden bind edilemez — ve bu yüzden neden beyaz liste şart.

AJAX API Referansı

Tüm istekler POST ile system/ajax.php adresine yapılır ve geçerli bir csrf_token içermelidir. Yanıtlar application/json türündedir.

action=list — DataTables listeleme

İstek: draw, start, length, search[value], order[0][column], order[0][dir]

Yanıt:

{
  "draw": 1,
  "recordsTotal": 50,
  "recordsFiltered": 50,
  "data": [[50, "<img …>", "Ozan", "TOPAL", "<span…>23.02.2025 23:28</span>", "<div class=\"cy-actions\">…</div>"]]
}

Sıralanabilir sütunlar beyaz listeyle sınırlıdır: 0 → id, 2 → name, 3 → surname, 4 → tarih.
Foto (1) ve İşlemler (5) sütunları veritabanı sütunu olmadıkları için sıralanamaz.

action=add — Yeni kayıt

İstek: name, surname, image_user (opsiyonel, multipart/form-data)

Başarılı (200):

{ "success": true, "type": "success", "description": "Kayıt başarıyla eklendi.", "id": 51 }

Doğrulama hatası (422):
{
  "success": false,
  "type": "danger",
  "description": "Lütfen formdaki hataları düzeltin.",
  "errors": { "name": "Ad alanı boş bırakılamaz." }
}

errors nesnesinin anahtarları form alanlarının id'leriyle birebir aynıdır; JavaScript mesajı doğrudan ilgili alanın altına yazar.

action=edit — Güncelleme

İstek: user_id, name, surname, image_user (opsiyonel)

Yeni görsel gönderilmezse mevcut görsel korunur. Gönderilirse yenisi kaydedilir ve eski dosya diskten silinir.

action=fetch — Tek kayıt (detay + düzenleme)

İstek: id

{
  "success": true,
  "id": 1,
  "name": "Evren",
  "surname": "ÇILGIN",
  "image": "2090273627.png",
  "image_url": "upload/2090273627.png",
  "tarih": "06.01.2025 19:34"
}

Hazır HTML değil ham veri döner; ekranı JavaScript .text() ile doldurduğu için XSS riski oluşmaz.

action=delete — Silme

İstek: id

Kayıt ve ilişkili görsel dosyası birlikte silinir. Kayıt yoksa 404 döner.

HTTP durum kodları

KodAnlamı
200İşlem başarılı
400Geçersiz parametre (örn. hatalı ID)
404Kayıt bulunamadı
405POST dışı istek
419CSRF token geçersiz veya oturum düşmüş
422Form doğrulama hatası (errors alanı döner)
500Sunucu / veritabanı hatası

Veritabanı Şeması

CREATE TABLE `users` (
  `id`      INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name`    VARCHAR(150) NOT NULL,
  `surname` VARCHAR(150) NOT NULL,
  `image`   VARCHAR(191) NOT NULL DEFAULT '',   -- sadece dosya adı, tam yol değil
  `tarih`   TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_users_name`    (`name`),             -- arama ve sıralama için
  KEY `idx_users_surname` (`surname`),
  KEY `idx_users_tarih`   (`tarih`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
KararNeden
InnoDB (MyISAM değil)Transaction ve foreign key desteği, satır bazlı kilitleme
utf8mb4 (utf8mb3 değil)Türkçe karakterler + emoji; eski utf8 bazı karakterleri saklayamaz
İndekslerArama/sıralama yapılan sütunlar; tablo büyüdükçe fark katlanarak açılır
Sadece dosya adıKlasör yapısı değişirse veritabanına dokunmak gerekmez

Mevcut (eski) bir kurulumu veri kaybetmeden yükseltmek için crud.sql dosyasının sonundaki ALTER TABLE komutlarını kullanın.



Sık Sorulanlar


Bu kodu kendi projemde kullanabilir miyim?

Evet. MIT lisanslı — ticari projeler dahil serbestçe kullanabilir, değiştirebilir, dağıtabilirsiniz. Atıf zorunlu değil ama sevindirir.

Tabloya yeni bir sütun eklemek istiyorum, nereleri değiştirmeliyim?

Örnek: email sütunu eklemek için beş nokta:

  1. crud.sql → tabloya sütunu ekleyin
  2. index.php → forma input, `'e ekleyin
  3. system/function.phpfind_user() içindeki SELECT listesine ekleyin
  4. system/ajax.phphandle_save() içinde doğrulama + INSERT/UPDATE, handle_list() içinde $data[] dizisine yeni hücre
  5. system/ajax.php → sütun eklediyseniz $sortableColumns` indekslerini kaydırmayı unutmayın

` sayısı ile $data[]` dizisinin uzunluğu aynı olmak zorundadır, aksi halde DataTables hata verir.

Görsel boyutu sınırını nasıl artırırım?

system/config.php içinde UPLOAD_MAX_BYTES değerini değiştirin. Ayrıca php.ini içindeki upload_max_filesize ve post_max_size değerlerini de artırın — PHP'nin limiti sizinkinden düşükse dosya sunucuya hiç ulaşmaz.

Neden hem istemcide hem sunucuda doğrulama var?

İstemci doğrulaması kullanıcı deneyimi içindir: kullanıcı sunucuya gitmeden anında geri bildirim alır. Ama JavaScript kapatılabilir veya istek doğrudan curl ile atılabilir. Bu yüzden gerçek koruma her zaman sunucudadır. İkisi birlikte kullanılır.

DataTables'ın serverSide: true ayarını kapatabilir miyim?

Kapatabilirsiniz ama o zaman tüm kayıtlar tek seferde tarayıcıya gönderilir. 50 kayıtta sorun olmaz; 50.000 kayıtta sayfa donar. Bu örnekte gerçek dünya senaryosunu göstermek için açık bırakıldı.

Bootstrap 5 sürümünü güncelleyebilir miyim?

Evet, assets/ altındaki dosyaları değiştirmeniz yeterli. Tasarım kalıbı Bootstrap'in üzerine ekleme yapar, onu değiştirmez — bu yüzden sürüm yükseltmeleri sorunsuz geçer.



Canlı Ortama Alırken


  • [ ] APP_DEBUG değerini false yapın
  • [ ] Veritabanı için root yerine sınırlı yetkili bir kullanıcı oluşturun
  • [ ] Kimlik bilgilerini ortam değişkeni olarak tanımlayın, koda gömmeyin
  • [ ] HTTPS kullanın; session.cookie_secure = 1 ve session.cookie_httponly = 1 ayarlayın
  • [ ] Nginx kullanıyorsanız .htaccess çalışmaz — yükleme klasöründe PHP'yi sunucu yapılandırmasından kapatın:

```nginx
location ^~ /upload/ {
location ~ \.php$ { deny all; }
}
```
  • [ ] upload/ klasörünü düzenli yedekleyin
  • [ ] Giriş sistemi ekleyin — bu örnekte kimlik doğrulama yoktur, herkes tüm kayıtları düzenleyebilir



Sorun Giderme


BelirtiÇözüm
"Veritabanına bağlanılamadı"MySQL çalışmıyor veya DB_* bilgileri hatalı. XAMPP panelinden MySQL'i başlatın.
Tablo boş, "Yükleniyor…" takılıTarayıcı konsolunu (F12) açın. Genelde system/ajax.php bir PHP hatası döndürüyordur; APP_DEBUG = true yapıp Network sekmesinden yanıtı okuyun.
HTTP 419 hatasıOturum düşmüş — sayfayı yenileyin. Sunucuda session.save_path yazılabilir olmalıdır.
Invalid parameter numberAynı isimli yer tutucuyu bir sorguda iki kez kullanmışsınız. EMULATE_PREPARES = false iken buna izin verilmez; farklı isimler verin.
$ is not definedJavaScript yükleme sırası bozulmuş. jQuery her zaman en başta gelmelidir.
"Görsel kaydedilemedi"upload/ klasörü yok veya yazma izni yok → chmod 755 upload
Türkçe karakterler bozukVeritabanı utf8mb4 değil. crud.sql sonundaki CONVERT TO CHARACTER SET utf8mb4 komutunu çalıştırın.
Büyük dosya yüklenmiyorphp.ini içindeki upload_max_filesize ve post_max_size değerlerini artırın.
DataTables "Requested unknown parameter"`` sayısı ile sunucudan dönen dizi uzunluğu farklı. İkisini eşitleyin.



Yol Haritası


  • [ ] Kullanıcı girişi ve rol tabanlı yetkilendirme
  • [ ] Toplu silme (checkbox ile çoklu seçim)
  • [ ] Excel / CSV / PDF dışa aktarma (DataTables Buttons)
  • [ ] Sunucu tarafında görsel yeniden boyutlandırma ve thumbnail
  • [ ] REST API katmanı (JWT ile)
  • [ ] Soft delete + işlem geçmişi (audit log)
  • [ ] PHPUnit ile birim testleri
  • [ ] Koyu tema için elle açma/kapama düğmesi



Katkı


Bu proje herkese açıktır — dilediğiniz geliştirmeyle katkı sağlayabilirsiniz.

📦 Depo: github.com/CilginYazilim/PHP-PDO-MySQL-Ajax-CRUD-DataTables-Bootstrap-5-Modals

Nasıl katkı sağlarım?Nereden
🐛 Hata bildirIssues
💡 Özellik önerIssues
🔧 Kod gönderPull Requests
❓ Soru sorDiscussions

Pull request adımları

# 1) Depoyu çatallayın (GitHub'da "Fork" butonu), sonra kendi kopyanızı indirin
git clone https://github.com/KULLANICI-ADINIZ/PHP-PDO-MySQL-Ajax-CRUD-DataTables-Bootstrap-5-Modals.git
cd PHP-PDO-MySQL-Ajax-CRUD-DataTables-Bootstrap-5-Modals

# 2) Değişikliğiniz için yeni bir dal açın
git checkout -b ozellik/yeni-ozellik

# 3) Kodunuzu yazın, sonra kaydedin
git add .
git commit -m "Yeni özellik: kısa ve açıklayıcı bir başlık"

# 4) Kendi çatalınıza gönderin
git push origin ozellik/yeni-ozellik

# 5) GitHub'da "Compare & pull request" butonuna tıklayın

Katkı ölçütleri

  • Kod açıklamalı olsun. Bu projenin temel amacı öğretmek; yorumsuz kod PR'ı geri döner.
  • Güvenlik kontrollerini atlamayın. Prepared statement, e() ile kaçışlama ve require_csrf() her yeni işlemde de olmalı.
  • Tasarım değişikliklerini cilginyazilim.css üzerinden yapın, satır içi style="..." kullanmayın.
  • Sütun eklerken ` sayısı ile $data[]` uzunluğunu eşitlemeyi unutmayın.
  • Yeni bir dış kütüphane eklemeden önce issue açıp tartışalım — proje bilinçli olarak bağımlılıksızdır.

Lisans

MIT — ticari kullanım dahil serbesttir.

cilginyazilim.com tarafından ❤ ile geliştirildi

Faydalı bulduysanız ⭐ vermeyi unutmayın.

Kaynak Kod soldaki ağaçtan bir dosya seçin

  • assets
    • css
      • bootstrap.css 232.4 KB
      • bootstrap.min.css 227.5 KB
      • cilginyazilim.css 19.4 KB
      • dataTables.bootstrap5.min.css 11.7 KB
      • style.css 2 KB
    • images
      • logo.png 70.4 KB
    • js
      • bootstrap.bundle.js 203.2 KB
      • bootstrap.js 142.3 KB
      • dataTables.bootstrap5.min.js 2.3 KB
      • jquery-3.7.0.js 278.3 KB
      • jquery.dataTables.min.js 85.1 KB
  • docs
    • screenshots
      • 01-liste.png 172.4 KB
      • 02-detay-modali.png 175.4 KB
      • 03-form-modali.png 168.7 KB
      • 04-sayfalama.png 201.5 KB
      • 05-arama.png 148.8 KB
      • README.md 987 B
  • system
    • .htaccess 1.9 KB
    • ajax.php 19.9 KB
    • config.local.php 143 B
    • config.local.php.example 1.3 KB
    • config.php 8.4 KB
    • function.php 16.7 KB
  • upload
    • .htaccess 357 B
    • 1130289535.png 3.1 KB
    • 1131702286.png 4.1 KB
    • 1832783644.png 70.4 KB
    • 2090273627.png 3.6 KB
  • .gitignore 1.1 KB
  • crud.sql 7 KB
  • index.php 36.8 KB
  • LICENSE 1.1 KB
  • README.en.md 27.2 KB
  • README.md 27.2 KB
Dosya seçilmedi
İncelemek istediğiniz dosyayı soldaki ağaçtan seçin.

Güvenlik gereği kaynak dosyalardaki parola, API anahtarı ve benzeri gizli değerler gösterilmeden önce maskelenir (••••••••).

Paylaş:

Sık Sorulan Sorular

Kullanıcıdan gelen hiçbir değer sorgu metnine yazılmaz. Tüm sorgular PDO'nun hazırlanmış ifadeleriyle çalışır: sorgunun yapısı önce veritabanına gönderilir, değerler ayrı parametre olarak bağlanır. Böylece bir değerin içindeki tırnak ya da SQL anahtar kelimesi sorgunun anlamını değiştiremez.

Veritabanından gelen her metin ekrana basılmadan önce kaçışlanır (htmlspecialchars). Böylece bir kaydın içine yazılmış HTML ya da betik, sayfada çalışacak kod olarak değil düz metin olarak görünür. Kaçışlama girişte değil çıkışta yapılır; veriyi bozmadan doğru katmanda çözmenin yolu budur.

Hayır. Klonlayın, crud.sql dosyasını içe aktarın, çalıştırın. Başka hiçbir kurulum adımı yoktur; Composer, npm ve hatta internet bağlantısı bile gerekmez, çünkü tüm kütüphaneler proje içinde durur. Paylaşımlı hostinglerde de doğrudan çalışır.

Yüklenen dosyanın türü, tarayıcının gönderdiği başlığa değil dosyanın gerçek içeriğine bakılarak doğrulanır ve yalnızca izin verilen görsel türleri kabul edilir. Dosya adı yeniden üretilir, böylece kullanıcının verdiği ad diske yazılan adı belirlemez. Daha derin bir savunma isterseniz kütüphanedeki güvenli dosya yükleme örneği on iki katmanlı sürümü anlatır.

Evet, MIT lisanslıdır ve tam olarak bunun için hazırlanmıştır. Tablo adını ve alanları kendi verinize göre değiştirip aynı kalıbı sürdürebilirsiniz: sunucu taraflı liste, modal form, Ajax uçları ve doğrulama akışı aynen kalır. Canlıya alırken hata gösterimini kapatmayı unutmayın.

Yorumlar 0 konuşma

Bu kod örneğine henüz yorum yapılmamış. Takıldığınız bir yer veya merak ettiğiniz bir ayrıntı varsa ilk soruyu siz sorun.

Soru Sor veya Yorum Yaz

Yorumunuz onaylandıktan sonra yayınlanır. Teknik sorularınıza ekibimiz yanıt verir.

Yayınlanmaz; yalnızca yanıt bildirimi için kullanılır.
En az 10 karakter.

İlgili Kod Örnekleri