Projects About me Blog FAQ Contact me

Building Dynamic Websites with PHP & JSON (No Database Required)

How I replaced MySQL with flat JSON files for lightning-fast content management in small-to-medium projects.

September 15, 2026 · BLOG
Building Dynamic Websites with PHP & JSON (No Database Required)

Building Dynamic Websites with PHP & JSON

When I started rebuilding my portfolio, I wanted something faster than WordPress but simpler than a full MVC framework. The answer? PHP reading and writing JSON files.

Why JSON Over MySQL?

For content that updates weekly—not every second—flat files are perfect:

  • Zero database latency (no connection overhead)
  • Git-friendly (content is version-controlled)
  • Portable (drag-and-drop to any host)
  • Cache-friendly (OPcache loves static reads)

The Architecture

<?php
// core/JsonStore.php
class JsonStore {
    private string $filePath;
    
    public function __construct(string $filename) {
        $this->filePath = __DIR__ . '/../data/' . $filename;
    }
    
    public function all(): array {
        if (!file_exists($this->filePath)) return [];
        $json = file_get_contents($this->filePath);
        return json_decode($json, true) ?? [];
    }
    
    public function findBySlug(string $slug): ?array {
        $items = $this->all();
        return array_values(array_filter($items, 
            fn($item) => $item['slug'] === $slug
        ))[0] ?? null;
    }
    
    public function save(array $data): bool {
        $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        return file_put_contents($this->filePath, $json, LOCK_EX) !== false;
    }
}

Usage in Your Pages

<?php
// blog.php
require_once 'core/JsonStore.php';
$blogStore = new JsonStore('posts.json');
$posts = array_filter($blogStore->all(), fn($p) => $p['published']);

// Sort by date descending
usort($posts, fn($a, $b) => strtotime($b['date']) - strtotime($a['date']));
?>

<?php foreach ($posts as $post): ?>
<article class="blog-card">
    <h2><?= htmlspecialchars($post['title']) ?></h2>
    <time datetime="<?= $post['date'] ?>"><?= date('M j, Y', strtotime($post['date'])) ?></time>
    <p><?= htmlspecialchars($post['excerpt']) ?></p>
    <a href="/post.php?slug=<?= urlencode($post['slug']) ?>">Read more →</a>
</article>
<?php endforeach; ?>

The Admin Interface

I built a simple admin panel that updates the JSON without touching code:

// admin.js - Save new post via fetch
async function savePost(postData) {
    const response = await fetch('/api/save-post.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(postData)
    });
    
    if (!response.ok) throw new Error('Save failed');
    return await response.json();
}

When NOT to Use This

Don't use JSON storage if:

  • You have multiple concurrent editors
  • You need complex relational queries
  • Content exceeds ~10,000 entries

The Result

My site now loads in under 200ms with zero database connections. For a portfolio and blog, that's perfect.

Sometimes the best database is no database at all.

More from the blog