İçindekiler (19)
- Gereksinimler ve Kurulum: Sistem İçin Ne Gereklidir?
- Temel Kavram ve İlk Çalışan Örnek: JSON Tabanlı Veri Depolama Nasıl Çalışır?
- Çekirdeğe Dokunmayan Eklenti Mimarisi (Zero-Core-Touch) Nasıl İnşa Edilir?
- Akıllı İçerik Ayrıştırıcı ve Otomatik Medya Gömme (Auto-Embed) Motoru
- Arama Motoru Optimizasyonu (SEO) ve Kalıcı 301 Yönlendirme Yönetimi
- Gerçekçi Senaryo: Favori Konu Senkronizasyonu ve Arayüz Vurgulama
- Yaygın Hatalar ve Çözüm Yolları
- Geleneksel SQL Forumlar ile Flat-File Mimarinin Karşılaştırması
- Güvenlik ve En İyi Uygulamalar (Best Practices)
- Sonuç
- Sık Sorulan Sorular
- Kaynaklar
- İleri Okuma
Birkaç zamandır kafaya takmıştım: veritabanı kendi içinde gömülü olan bir PHP forum scripti yazmak istiyordum. Sonunda başardım. Yaklaşık 2 haftalık bir süreç içinde bence hemen her tür özelliği olan güzel bir PHP script yazdım. Tam da bugün PHP'de önemli bir açık keşfedilmişken bu işi bitirdim.
Şimdi ben ne yaptım? Nedir bu flatbase veya veritabanı bağımsız (gömülü) mimari? Kabaca anlatayım.
Veritabanı bağımsız forum mimarisi, ilişkisel veritabanı yönetim sistemlerine (RDBMS) ihtiyaç duymadan tüm verileri doğrudan dosya sistemi üzerinde yapılandırılmış JSON belgeleri halinde saklayan yüksek performanslı bir web yazılımı yaklaşımıdır. Geleneksel forum yazılımlarının getirdiği SQL sunucu yükü, karmaşık tablo indeksleri ve yüksek bellek tüketimi, modern web dünyasında yerini mikrosaniyeler mertebesinde çalışan dosya tabanlı motorlara bırakmaktadır. Bu makalede; çekirdek kodlara müdahale gerektirmeyen (Zero-Core-Touch) kanca mimarisi, zengin medya gömme ayrıştırıcıları, SEO odaklı kalıcı 301 yönlendirme mekanizmaları ve atomik dosya kilitleme prensipleriyle baştan sona modern bir flat-file forum altyapısının nasıl inşa edildiğini inceleyeceğiz.
Gereksinimler ve Kurulum: Sistem İçin Ne Gereklidir?
Modern bir flat-file forum altyapısını sorunsuz bir şekilde çalıştırmak için sunucu tarafında en az PHP 8.2 sürümünün kurulu olması, JSON eklentisinin aktif edilmesi ve depolama dizininde yazma yetkilerinin yapılandırılması gerekmektedir. Sistem, üçüncü taraf harici kütüphanelere ve ağır ORM (Object-Relational Mapping) katmanlarına ihtiyaç duymayacak şekilde saf PHP çekirdeği üzerinde optimize edilmiştir.
Temel Kavram ve İlk Çalışan Örnek: JSON Tabanlı Veri Depolama Nasıl Çalışır?
Flat-file mimarisinde veri kalıcılığı, veritabanı tabloları yerine diskteki JSON dosyalarının atomik olarak kilitlenmesi ve güncellenmesi prensibiyle sağlanır. Eşzamanlı gelen HTTP isteklerinin aynı dosya üzerinde veri kaybına (race condition) yol açmaması için PHP'nin yerleşik flock mekanizmasından yararlanılır.
Aşağıdaki kod bloğu, forumun kalbi olan ve diskten veri okuma ile güvenli atomik veri yazma işlemlerini yürüten Storage sınıfının çekirdek motorunu içermektedir.
<?php
declare(strict_types=1);
final class Storage
{
private static string $storagePath = __DIR__ . '/../storage/';
/**
* Belirtilen JSON dosyasını okur ve diziye dönüştürür.
*
* @param string $filename
* @param array<string, mixed> $default
* @return array<string, mixed>
*/
public static function readJson(string $filename, array $default = []): array
{
$filePath = self::$storagePath . ltrim($filename, '/');
if (!is_file($filePath)) {
return $default;
}
$content = @file_get_contents($filePath);
if ($content === false || trim($content) === '') {
return $default;
}
$data = json_decode($content, true, 512, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
return is_array($data) ? $data : $default;
}
/**
* Dosyayı kilitler, değiştirici fonksiyonu uygular ve diske yazar.
*
* @param string $filename
* @param callable(array<string, mixed>): array<string, mixed> $modifier
* @return bool
*/
public static function updateJson(string $filename, callable $modifier): bool
{
$filePath = self::$storagePath . ltrim($filename, '/');
$fp = @fopen($filePath, 'c+');
if (!$fp) {
return false;
}
if (flock($fp, LOCK_EX)) {
$fileSize = filesize($filePath);
$raw = $fileSize > 0 ? (string) fread($fp, $fileSize) : '{}';
$data = json_decode($raw, true) ?: [];
$modifiedData = $modifier($data);
$jsonOutput = json_encode($modifiedData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
ftruncate($fp, 0);
rewind($fp);
fwrite($fp, $jsonOutput);
fflush($fp);
flock($fp, LOCK_UN);
fclose($fp);
return true;
}
fclose($fp);
return false;
}
}
Bu kod bloğunda yer alan fopen fonksiyonundaki c+ modu, dosya mevcut değilse oluşturur, mevcutsa içeriği hemen sıfırlamadan okuma ve yazma amacıyla işaretçiyi dosyanın başına koyar. LOCK_EX (Exclusive Lock) bayrağı ise işletim sistemi düzeyinde bir kilit oluşturarak iki farklı PHP sürecinin aynı anda dosyayı ezmesini engeller.
Çekirdeğe Dokunmayan Eklenti Mimarisi (Zero-Core-Touch) Nasıl İnşa Edilir?
Zero-Core-Touch eklenti mimarisi, ana sistem dosyalarından tek bir satır dahi değiştirmeden forumun işlevselliğini genişletmeye yarayan olay odaklı (event-driven) bir kanca sistemidir. Sistemde tanımlanan eylemler (Actions) yeni kod yürütülmesini tetiklerken, filtreler (Filters) ekrana basılacak verilerin manipüle edilmesini sağlar.
Aşağıdaki kod bloğunda, çekirdeğin olay dinleyicilerini yöneten Plugin kanca yöneticisi yer almaktadır.
<?php
declare(strict_types=1);
final class Plugin
{
/** @var array<string, array<int, array<int, callable>>> */
private static array $actions = [];
/** @var array<string, array<int, array<int, callable>>> */
private static array $filters = [];
public static function addAction(string $hook, callable $callback, int $priority = 10): void
{
self::$actions[$hook][$priority][] = $callback;
}
public static function doAction(string $hook, mixed ...$args): void
{
if (empty(self::$actions[$hook])) {
return;
}
ksort(self::$actions[$hook]);
foreach (self::$actions[$hook] as $callbacks) {
foreach ($callbacks as $cb) {
$cb(...$args);
}
}
}
public static function addFilter(string $hook, callable $callback, int $priority = 10): void
{
self::$filters[$hook][$priority][] = $callback;
}
public static function applyFilters(string $hook, mixed $value, mixed ...$args): mixed
{
if (empty(self::$filters[$hook])) {
return $value;
}
ksort(self::$filters[$hook]);
foreach (self::$filters[$hook] as $callbacks) {
foreach ($callbacks as $cb) {
$value = $cb($value, ...$args);
}
}
return $value;
}
}
Burada kullanılan ksort fonksiyonu, kancaya bağlanan işlevlerin öncelik (priority) değerlerine göre küçükten büyüğe sıralı bir biçimde işletilmesini temin eder. Böylece güvenlik filtreleri veya arayüz modalleri sisteme tam zamanında enjekte edilebilir.
Bir eklentinin kendi stil dosyalarını ve scriptlerini sisteme nasıl gömebileceğini göstermek adına, kod bloklarına tek tıkla kopyalama özelliği kazandıran bağımsız eklenti örneği aşağıda verilmiştir.
<?php
declare(strict_types=1);
/**
* Plugin Name: Kod Kopyalama Butonu
* Description: Mesajlardaki pre etiketlerine bağımsız kopyalama butonu ekler.
* Version: 1.0.0
*/
Plugin::addAction('theme_footer_after', static function (): void {
?>
<style id="ff-plugin-code-copy-style">
.code-block-wrapper { position: relative; margin: 1rem 0; }
.code-copy-btn {
position: absolute; top: 0.5rem; right: 0.5rem;
background: #1e293b; color: #cbd5e1; border: 1px solid #334155;
border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.75rem;
cursor: pointer; transition: all 0.15s ease;
}
.code-copy-btn.copied { background: #16a34a; color: #ffffff; }
</style>
<script id="ff-plugin-code-copy-script">
(function() {
document.querySelectorAll('.post-body pre').forEach(function(block) {
if (block.closest('.code-block-wrapper')) return;
var wrapper = document.createElement('div');
wrapper.className = 'code-block-wrapper';
block.parentNode.insertBefore(wrapper, block);
wrapper.appendChild(block);
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'code-copy-btn';
btn.textContent = 'Kopyala';
btn.addEventListener('click', function() {
var codeText = block.innerText.replace('Kopyala', '').trim();
navigator.clipboard.writeText(codeText).then(function() {
btn.classList.add('copied');
btn.textContent = 'Kopyalandı! ✓';
setTimeout(function() {
btn.classList.remove('copied');
btn.textContent = 'Kopyala';
}, 2000);
});
});
wrapper.appendChild(btn);
});
})();
</script>
<?php
});
Bu eklenti örneği, theme_footer_after kancasını kullanarak HTML gövdesi kapatılmadan hemen önce CSS ve JavaScript varlıklarını sayfaya dahil eder. Eklenti klasörü silindiğinde veya devreden çıkarıldığında temanın style.css dosyasında hiçbir atık kod kalmaz.
Akıllı İçerik Ayrıştırıcı ve Otomatik Medya Gömme (Auto-Embed) Motoru
Akıllı içerik ayrıştırıcı motoru, üyelerin mesaj içerisine çıplak (raw URL) biçimde yapıştırdığı video, müzik veya sosyal medya bağlantılarını düzenli ifadelerle tespit ederek cihaza uyumlu görsel oynatıcılara dönüştüren bileşendir. Motor, URL yapısından medyanın yönelimini (dikey veya yatay) otomatik analiz eder.
Aşağıdaki kod bloğunda; YouTube Shorts, standart YouTube, Spotify ve dikey Facebook Reels videolarını ayırt ederek doğru en-boy oranına (aspect ratio) oturtan ayrıştırıcı fonksiyonu yer almaktadır.
<?php
declare(strict_types=1);
final class EmbedParser
{
public static function buildEmbedHtml(string $url): ?string
{
// 1. YouTube Shorts (Dikey 9:16 Oynatıcı)
if (preg_match('/youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/i', $url, $matches)) {
$videoId = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
return '<div class="embed-center-wrap">'
. '<div class="embed-responsive embed-shorts" style="max-width:340px;aspect-ratio:9/16;margin:0 auto;">'
. '<iframe src="[https://www.youtube.com/embed/](https://www.youtube.com/embed/)' . $videoId . '" loading="lazy" allowfullscreen></iframe>'
. '</div></div>';
}
// 2. Standart YouTube (Yatay 16:9 Oynatıcı)
if (preg_match('/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/i', $url, $matches)) {
$videoId = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
return '<div class="embed-center-wrap">'
. '<div class="embed-responsive embed-youtube" style="aspect-ratio:16/9;width:100%;">'
. '<iframe src="[https://www.youtube.com/embed/](https://www.youtube.com/embed/)' . $videoId . '" loading="lazy" allowfullscreen></iframe>'
. '</div></div>';
}
// 3. Facebook Reels ve Normal Video Ayrımı
if (preg_match('/facebook\.com\/(reel|videos|watch)/i', $url)) {
$isReel = (bool) preg_match('/facebook\.com\/reel/i', $url);
$ratioStyle = $isReel ? 'max-width:340px;aspect-ratio:9/16;margin:0 auto;' : 'aspect-ratio:16/9;width:100%;';
$encoded = urlencode($url);
return '<div class="embed-center-wrap">'
. '<div class="embed-responsive" style="' . $ratioStyle . '">'
. '<iframe src="[https://www.facebook.com/plugins/video.php?href=](https://www.facebook.com/plugins/video.php?href=)' . $encoded . '&show_text=false" loading="lazy" allowfullscreen></iframe>'
. '</div></div>';
}
// 4. Spotify Oynatıcı (Şarkı: 152px, Çalma Listesi: 352px Dinamik Yükseklik)
if (preg_match('/open\.spotify\.com\/(track|album|playlist)\/([a-zA-Z0-9]+)/i', $url, $matches)) {
$type = strtolower($matches[1]);
$spotifyId = htmlspecialchars($matches[2], ENT_QUOTES, 'UTF-8');
$height = ($type === 'track') ? '152' : '352';
return '<div class="embed-center-wrap" style="width:100%;max-width:680px;">'
. '<iframe src="[https://open.spotify.com/embed/](https://open.spotify.com/embed/)' . $type . '/' . $spotifyId . '" height="' . $height . '" style="width:100%;border-radius:12px;border:0;" loading="lazy"></iframe>'
. '</div>';
}
return null;
}
}
Yukarıdaki implementasyonda modern CSS aspect-ratio özelliği kullanılmıştır. Böylece CSS dosyasına aşırı bağımlılık azaltılmış, mobil cihazlarda dikey video izlenirken iframe taşmalarının önüne geçilmiştir.
Arama Motoru Optimizasyonu (SEO) ve Kalıcı 301 Yönlendirme Yönetimi
Kalıcı 301 yönlendirme mekanizması, birleştirilen veya taşınan tartışma konularının eski bağlantı adreslerini indeksleyen arama motoru botlarının 404 hatası almasını önleyerek sayfa otoritesini koruyan yapıdır. Birleştirme anında eski konu numarası bir hedef ID ile haritalandırılır.
Aşağıdaki kod bloğunda; silinmiş veya birleştirilmiş konuların istek anında kontrol edildiği ve dinamik 301 yönlendirmesiyle güvenli hedefe aktarıldığı kontrolcü katmanı gösterilmektedir.
<?php
declare(strict_types=1);
final class ThreadRoutingController
{
public static function resolveThread(int $threadId): void
{
$thread = Storage::readJson('threads/' . $threadId . '.json', []);
// Konu dosyası mevcut değilse yönlendirme tablosunu tara
if (empty($thread)) {
$redirects = Storage::readJson('redirects.json', []);
$targetThreadId = (int) ($redirects[(string) $threadId] ?? 0);
if ($targetThreadId > 0) {
$targetUrl = '/konu/' . $targetThreadId . '/';
http_response_code(301);
header('Location: ' . $targetUrl);
exit;
}
// Haritada da yoksa standart 404 sayfasına yönlendir
http_response_code(404);
require __DIR__ . '/../themes/default/404.php';
exit;
}
// Konu bulunduysa sayfayı oluştur
require __DIR__ . '/../themes/default/thread.php';
}
}
Bu yaklaşım sayesinde, iki konu birleştirildiğinde veritabanı silme işlemi yapılsa bile redirects.json dosyası geçmiş indeks trafiğini yakalar. Arama motorları dizinlerindeki eski bağlantıyı yenisiyle sorunsuz biçimde günceller.
Gerçekçi Senaryo: Favori Konu Senkronizasyonu ve Arayüz Vurgulama
Favori konu mekanizması; oturum açmış kullanıcının beğendiği veya takip etmek istediği konuları hem kendi profiline kaydetmesini hem de konu listelerinde bu içeriklerin görsel olarak belirginleşmesini sağlar. Bu çift yönlü senkronizasyon, dizin dosyası ile kullanıcı profilinin aynı anda güncellenmesiyle yürütülür.
Aşağıdaki kod parçası, kullanıcının favori listesini tersine çeviren (toggle) ve ana sayfa indeksini senkronize eden servis fonksiyonudur.
<?php
declare(strict_types=1);
final class FavoriteService
{
public static function toggle(int $threadId, int $userId): bool
{
if ($threadId <= 0 || $userId <= 0) {
return false;
}
$isFavorited = false;
// 1. Kullanıcı profilindeki favori listesini güncelle
Storage::updateJson('users/' . $userId . '.json', static function (array $user) use ($threadId, &$isFavorited): array {
$favs = array_map('intval', (array) ($user['favorites'] ?? []));
if (in_array($threadId, $favs, true)) {
$favs = array_values(array_filter($favs, static fn(int $id): bool => $id !== $threadId));
$isFavorited = false;
} else {
$favs[] = $threadId;
$isFavorited = true;
}
$user['favorites'] = array_unique($favs);
return $user;
});
// 2. threads_index.json dosyasını senkronize et
Storage::updateJson('threads_index.json', static function (array $index) use ($threadId, $userId, $isFavorited): array {
foreach ($index as $k => $item) {
if ((int) ($item['id'] ?? 0) === $threadId) {
$favs = array_map('intval', (array) ($item['favorites'] ?? []));
if ($isFavorited) {
$favs[] = $userId;
} else {
$favs = array_values(array_filter($favs, static fn(int $id): bool => $id !== $userId));
}
$index[$k]['favorites'] = array_values(array_unique($favs));
break;
}
}
return $index;
});
return $isFavorited;
}
}
Yukarıdaki işlem tamamlandıktan sonra, şablon motoru liste basılırken aktif kullanıcının favorilediği konulara açık mavi bir arayüz stili atar. Aşağıdaki şablon örneği bu render sürecini göstermektedir.
<?php
declare(strict_types=1);
$currentUserId = 1; // Aktif oturum açmış kullanıcı ID
$userFavThreadIds = [12, 45, 89]; // Kullanıcının oturumundaki favori ID listesi
?>
<!-- Konu Listeleme Döngüsü -->
<?php foreach ($threads as $t): ?>
<?php
$tId = (int) ($t['id'] ?? 0);
$isFav = in_array($tId, $userFavThreadIds, true);
?>
<article class="thread-item <?= $isFav ? 'is-favorited-thread' : '' ?>">
<h2 class="thread-title">
<a href="/konu/<?= $tId ?>/"><?= htmlspecialchars((string)$t['title'], ENT_QUOTES, 'UTF-8') ?></a>
</h2>
</article>
<?php endforeach; ?>
<style>
.thread-item.is-favorited-thread {
background: #eff6ff !important;
border-left: 3px solid #3b82f6 !important;
}
</style>
Bu şablon mantığında, in_array fonksiyonunun üçüncü parametresine true (strict mode) değeri verilerek tür güvenliği garanti edilmiş ve integer karşılaştırması üzerinden yüksek hız elde edilmiştir.
Yaygın Hatalar ve Çözüm Yolları
Flat-file forum geliştirmede en sık karşılaşılan teknik problem, disk tabanlı işlemlerin eşzamanlı istekler altında bozulması ve yanlış CSRF konfigürasyonları nedeniyle form gönderimlerinin sessizce reddedilmesidir.
1. JSON Dosyalarında Veri Yarışı (Race Condition) Hatası
Hata Mesajı: SyntaxError: Unexpected end of JSON input veya verilerin rastgele silinmesi.
Nedeni: Dosya file_put_contents veya kilitsiz fopen ile yazılırken aynı anda gelen ikinci bir isteğin dosyayı boş okuması veya üzerine yarım yazmasıdır.
// YANLIŞ: Eşzamanlı isteklerde dosyayı bozar
$data = json_decode(file_get_contents('threads.json'), true);
$data[] = $newThread;
file_put_contents('threads.json', json_encode($data));
// DOĞRU: Atomik dosya kilidiyle okuma ve yazma koruması
Storage::updateJson('threads.json', static function(array $data) use ($newThread): array {
$data[] = $newThread;
return $data;
});
2. Localhost ve Proxy Arkasında CSRF Doğrulama Başarısızlığı
Hata Mesajı: Güvenlik (CSRF) doğrulaması başarısız oldu.
Nedeni: Sunucunun katı HTTP Origin ve Referer başlıklarını kontrol etmesi, port numarası veya SSL yönlendirmesi içeren yerel ortamlarda eşleşmenin bozulmasıdır.
// YANLIŞ: Aşırı katı ve port değişikliklerinde başarısız olan doğrulama
if ($_SERVER['HTTP_ORIGIN'] !== '[https://example.com](https://example.com)') {
throw new Exception('CSRF origin mismatch');
}
// DOĞRU: Kriptografik oturum tokenini doğrulayan güvenli kontrol
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
throw new Exception('Geçersiz güvenlik bileti.');
}
Geleneksel SQL Forumlar ile Flat-File Mimarinin Karşılaştırması
Aşağıdaki karşılaştırma tablosu, veritabanı bağımsız mimari ile klasik SQL tabanlı topluluk yazılımlarının mimari farklarını özetlemektedir.
| Mimari Kriter | Geleneksel SQL Forumlar (vBulletin, XenForo, phpBB) | FlatForum (Modern Flat-File & JSON) |
|---|---|---|
| Veritabanı Bağımlılığı | MySQL / MariaDB / PostgreSQL zorunludur. | Sıfır bağımlılık; yalnızca dosya sistemi kullanılır. |
| Yedekleme Kolaylığı | SQL dökümü (dump) ve tablo kilitleri gerektirir. | Doğrudan storage/ klasörünü kopyalamak yeterlidir. |
| Gecikme Süresi (Latency) | TCP bağlantısı ve sorgu derleme gecikmesi bulunur. | Doğrudan RAM disk / NVMe dosya okuma hızındadır. |
| Eklenti İzolasyonu | Veritabanı şemasına tablo ve sütun eklenmesini gerektirir. | İzole JSON dosyaları ve bağımsız kancalarla çalışır. |
| Sunucu Maliyeti | Yüksek RAM ve optimize edilmiş DB motoru ister. | En düşük konfigürasyonlu paylaşımlı sunucularda dahi çalışır. |
Güvenlik ve En İyi Uygulamalar (Best Practices)
Flat-file sistemlerde en yüksek öncelik, web tarayıcılarının storage/*.json dosyalarına doğrudan URL üzerinden erişmesini engellemektir. Veri klasörleri genel erişime açık tutulduğunda kullanıcı bilgileri doğrudan ifşa olabilir.
- Depolama Dizinini Kapatın:
storage/dizini içerisine bir.htaccessdosyası yerleştirerek veya Nginx yapılandırmasındalocation ^~ /storage/ { deny all; }kuralını tanımlayarak doğrudan HTTP erişimini engelleyin. - XSS Koruması: Şablonlara basılan tüm kullanıcı girdilerini istisnasız
htmlspecialchars($str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')süzgecinden geçirin. - Kriptografik Tokenlar: Form onaylarında tahmin edilemez token üretimi için daima
random_bytes(32)fonksiyonunu kullanın. - Bellek Sınırları: Çok büyük tartışma konularında tüm JSON dosyasını hafızaya alıp döngüye sokmak yerine, sayfalama (pagination) sınırlarına göre yalnızca ilgili mesaj dilimini ayrıştırın.
Sonuç
Flat-file forum mimarisi; SQL sunucu yönetimi, indeks şişmesi ve yüksek kaynak tüketimi gibi geleneksel forum yazılımlarının getirdiği yükleri ortadan kaldıran modern ve çevik bir alternatiftir. Doğru bir atomik dosya kilitleme sistemi, çekirdeğe dokunmayan kanca yapısı ve modern içerik ayrıştırıcıları ile donatıldığında, hem geliştirici deneyimi hem de son kullanıcı hızı açısından son derece verimli bir topluluk platformu inşa etmek mümkündür.
Sık Sorulan Sorular
Flat-file forum sistemleri kaç aktif üyeye kadar performanslı çalışabilir?
Modern NVMe SSD sunucularda ve doğru sayfalama kurgusunda flat-file mimariler on binlerce konuyu ve yüz binlerce mesajı sorunsuz şekilde yönetebilir. Bellek tüketimi dosya boyutuna değil sayfa başına çekilen veri dilimine bağlı olduğu için performans kaybı yaşanmaz.
JSON dosyalarına aynı anda yazma yapıldığında veriler bozulur mu?
İşletim sistemi düzeyinde çalışan flock ve LOCK_EX kilitleri kullanıldığında dosyaya aynı anda yalnızca bir işlem yazabilir. Diğer süreçler kilit çözülene kadar kuyrukta bekletildiğinden veri bozulması veya çakışma yaşanmaz.
Sunucu taşırken forum verilerini aktarmak ne kadar sürer?
Veritabanı dışa aktarma (export) veya tablo içe aktarma (import) adımları bulunmadığından taşıma işlemi yalnızca dosyaların kopyalanmasından ibarettir. storage/ dizininin yeni sunucuya aktarılması ve dosya izinlerinin verilmesiyle forum saniyeler içinde yayına hazır hale gelir.
Çıplak linklerin otomatik gömülmesi (Auto-Embed) sayfa hızını düşürür mü?
Tüm gömülü medya çerçevelerine loading="lazy" özelliği tanımlandığı için tarayıcı yalnızca ekranda görünen medyaları yükler. Böylece sayfa açılış hızı olumsuz etkilenmez ve veri tasarrufu sağlanır.
Kaynaklar
- PHP Group, "PHP 8.2 Sürüm Notları ve Tip Sistemi Güncellemeleri", 2022. php.net/releases/8.2
- PHP Manual, "Filesystem Functions - flock Reference", 2024. php.net/manual/en/function.flock.php
- OWASP Foundation, "Cross-Site Request Forgery Prevention Cheat Sheet", 2023. cheatsheetseries.owasp.org
- World Wide Web Consortium (W3C), "HTML Living Standard: The iframe and aspect-ratio specification", 2024. html.spec.whatwg.org
İleri Okuma
- Martin Fowler, "Patterns of Enterprise Application Architecture", Addison-Wesley, 2002.
- Rasmus Lerdorf, Kevin Tatroe, Peter MacIntyre, "Programming PHP: Creating Dynamic Web Pages", O'Reilly Media, 2020.
- RFC 7231, "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Section 6.4.2: 301 Moved Permanently", IETF, 2014.




