Project: Blog Sederhana dengan PHP Native (Bagian 1)
Setelah membuat toko online mini, sekarang kita naik satu level: membangun blog sederhana dengan PHP Native. Project ini realistis karena menggabungkan banyak skill penting sekaligus:
- koneksi database
- relasi kategori dan artikel
- halaman admin
- slug URL
- status draft vs published
- pagination di halaman publik
Di bagian pertama ini, kita fokus menyiapkan database, struktur folder, helper, dan dashboard admin dasar.
1. Gambaran Fitur Project
Target akhir blog yang akan kita bangun:
- Admin bisa membuat kategori.
- Admin bisa menulis artikel.
- Artikel bisa disimpan sebagai
draft atau published.
- Halaman publik menampilkan daftar artikel dengan pagination.
- Setiap artikel punya URL detail berbasis slug.
2. Membuat Database
Buat database baru:
CREATE DATABASE blog_sederhana;
USE blog_sederhana;
Lalu buat tabel kategori dan artikel:
CREATE TABLE kategori (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_kategori VARCHAR(100) NOT NULL,
slug VARCHAR(120) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE artikel (
id INT AUTO_INCREMENT PRIMARY KEY,
kategori_id INT NOT NULL,
judul VARCHAR(180) NOT NULL,
slug VARCHAR(200) NOT NULL UNIQUE,
ringkasan TEXT NOT NULL,
isi LONGTEXT NOT NULL,
thumbnail VARCHAR(255) DEFAULT NULL,
status ENUM('draft', 'published') DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (kategori_id) REFERENCES kategori(id) ON DELETE RESTRICT
);
Masukkan data awal:
INSERT INTO kategori (nama_kategori, slug) VALUES
('PHP Dasar', 'php-dasar'),
('Project', 'project'),
('Tips Belajar', 'tips-belajar');
INSERT INTO artikel (kategori_id, judul, slug, ringkasan, isi, status) VALUES
(1, 'Cara Belajar PHP untuk Pemula', 'cara-belajar-php-untuk-pemula', 'Langkah bertahap untuk mulai belajar PHP tanpa bingung.', '<p>Isi artikel awal...</p>', 'published'),
(2, 'Membangun CRUD Artikel Pertama', 'membangun-crud-artikel-pertama', 'Struktur sederhana untuk latihan CRUD.', '<p>Isi artikel project...</p>', 'draft');
3. Struktur Folder Project
Buat folder baru blog-sederhana dengan struktur seperti ini:
blog-sederhana/
├── admin/
│ ├── index.php
│ ├── kategori.php
│ ├── artikel-form.php
│ └── proses-artikel.php
├── assets/
│ └── style.css
├── config/
│ └── database.php
├── uploads/
├── functions.php
└── public/
├── index.php
└── detail.php
Penjelasan singkat:
admin/ untuk area kelola konten
public/ untuk halaman yang dibuka pengunjung
config/ untuk koneksi database
functions.php untuk helper bersama
uploads/ untuk thumbnail artikel
4. Membuat Koneksi Database
Isi file config/database.php:
<?php
$host = '127.0.0.1';
$db = 'blog_sederhana';
$user = 'root';
$pass = '';
try {
$pdo = new PDO("mysql:host={$host};dbname={$db};charset=utf8mb4", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die('Koneksi database gagal: ' . $e->getMessage());
}
5. Membuat Helper Dasar
Buat file functions.php:
<?php
function slugify(string $text): string
{
$text = strtolower(trim($text));
$text = preg_replace('/[^a-z0-9]+/i', '-', $text);
return trim($text, '-');
}
function excerpt(string $html, int $limit = 140): string
{
$text = strip_tags($html);
if (strlen($text) <= $limit) {
return $text;
}
return substr($text, 0, $limit) . '...';
}
function badgeStatus(string $status): string
{
return $status === 'published' ? '✅ Published' : '📝 Draft';
}
Helper ini akan sering dipakai:
slugify() untuk URL rapi seperti /detail.php?slug=belajar-php
excerpt() untuk ringkasan di daftar artikel
badgeStatus() untuk tampilan status di dashboard admin
6. Membuat Dashboard Admin Dasar
Sekarang buat file admin/index.php:
<?php
require __DIR__ . '/../config/database.php';
require __DIR__ . '/../functions.php';
$stmt = $pdo->query("
SELECT artikel.*, kategori.nama_kategori
FROM artikel
INNER JOIN kategori ON kategori.id = artikel.kategori_id
ORDER BY artikel.created_at DESC
");
$artikels = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Admin Blog</title>
<link rel="stylesheet" href="../assets/style.css">
</head>
<body>
<div class="container">
<div class="page-header">
<div>
<h1>Dashboard Blog</h1>
<p>Kelola artikel dan kategori dari satu tempat.</p>
</div>
<div class="actions">
<a class="btn secondary" href="kategori.php">Kelola Kategori</a>
<a class="btn" href="artikel-form.php">+ Artikel Baru</a>
</div>
</div>
<table>
<thead>
<tr>
<th>Judul</th>
<th>Kategori</th>
<th>Status</th>
<th>Dibuat</th>
</tr>
</thead>
<tbody>
<?php foreach ($artikels as $artikel): ?>
<tr>
<td><?= htmlspecialchars($artikel['judul']) ?></td>
<td><?= htmlspecialchars($artikel['nama_kategori']) ?></td>
<td><?= badgeStatus($artikel['status']) ?></td>
<td><?= htmlspecialchars($artikel['created_at']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</body>
</html>
7. Styling Dasar
Isi file assets/style.css dengan style sederhana:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: "Segoe UI", Tahoma, sans-serif;
background: #f5f7fb;
color: #1f2937;
}
.container {
max-width: 980px;
margin: 40px auto;
padding: 0 16px;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
margin-bottom: 24px;
}
.actions {
display: flex;
gap: 12px;
}
.btn {
display: inline-block;
padding: 10px 16px;
border-radius: 8px;
background: #2563eb;
color: white;
text-decoration: none;
}
.btn.secondary {
background: #475569;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 12px;
overflow: hidden;
}
th,
td {
padding: 14px 16px;
border-bottom: 1px solid #e5e7eb;
text-align: left;
}
th {
background: #0f172a;
color: white;
}
Checklist Setelah Bagian 1
Kalau langkah di atas berhasil, kamu sekarang sudah punya:
- database blog
- tabel kategori dan artikel
- dashboard admin dasar
- helper untuk slug dan excerpt
- struktur folder yang siap dikembangkan
Error Umum
SQLSTATE saat membuka dashboard admin
Biasanya nama database, tabel, atau kolom tidak sama dengan query yang dipakai.
Halaman putih kosong
Sering terjadi karena file database.php atau functions.php tidak berhasil di-require. Cek path file dengan teliti.
Unknown column 'nama_kategori'
Kolom itu berasal dari hasil JOIN. Pastikan query memakai:
INNER JOIN kategori ON kategori.id = artikel.kategori_id
Selanjutnya
Fondasi project sudah siap. Di bagian berikutnya, kita akan membuat:
- CRUD kategori
- form artikel
- simpan draft vs published
- editor WYSIWYG untuk isi artikel
Lanjut ke Blog Sederhana Bagian 2 →