🏫 Tutorial Website Sekolah dengan PHP
Panduan lengkap membuat website sekolah dari nol untuk siswa
🚀 Pengenalan PHP untuk Website Sekolah
Apa itu PHP?
PHP adalah bahasa pemrograman yang berjalan di server untuk membuat website dinamis. Berbeda dengan HTML yang statis, PHP bisa menampilkan data yang berubah-ubah seperti daftar siswa, nilai, atau berita sekolah.
Yang akan kita buat:
- 🏠 Halaman utama sekolah
- 📰 Sistem berita/pengumuman
- 👥 Profil guru dan siswa
- 📚 Informasi akademik
- 📞 Halaman kontak
💡 Yang perlu disiapkan:
- XAMPP (untuk menjalankan PHP di komputer)
- Text editor (Notepad++, VS Code, atau Sublime Text)
- Browser web (Chrome, Firefox, dll)
Mengapa belajar dengan cara ini?
Tutorial ini dibuat agar setiap file berdiri sendiri dan mudah dipahami. Kalian bisa melihat bagaimana setiap bagian bekerja secara terpisah, lalu menggabungkannya menjadi website yang utuh.
📁 Struktur Folder Website
Mengapa struktur folder penting?
Struktur folder yang rapi membuat website mudah dikelola dan dikembangkan. Setiap jenis file diletakkan di tempat yang sesuai.
Struktur Folder Website Sekolah:
Penjelasan setiap folder:
- Root folder: Berisi file PHP utama (halaman-halaman website)
- css/: Berisi file CSS untuk styling/tampilan
- js/: Berisi file JavaScript untuk interaksi
- images/: Berisi gambar-gambar website
- components/: Berisi komponen yang bisa dipakai ulang
- config/: Berisi konfigurasi database dan pengaturan
💡 Tips Penamaan File:
- Gunakan huruf kecil semua
- Pisahkan kata dengan tanda minus (-) atau underscore (_)
- Hindari spasi dalam nama file
- Gunakan nama yang deskriptif
🏠 Membuat File Index.php
Apa itu index.php?
Index.php adalah halaman utama website yang pertama kali dilihat pengunjung. File ini menggabungkan HTML untuk struktur dan PHP untuk konten dinamis.
<?php // File: index.php // Halaman utama website sekolah // Informasi sekolah (nanti bisa diambil dari database) $nama_sekolah = "SMA Negeri 1 Contoh"; $alamat_sekolah = "Jl. Pendidikan No. 123, Jakarta"; $tahun_berdiri = 1985; // Data berita terbaru $berita = [ [ 'judul' => 'Penerimaan Siswa Baru 2024', 'tanggal' => '15 Januari 2024', 'isi' => 'Pendaftaran siswa baru telah dibuka...' ], [ 'judul' => 'Prestasi Olimpiade Matematika', 'tanggal' => '10 Januari 2024', 'isi' => 'Siswa kami meraih juara 1 olimpiade...' ] ]; ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?php echo $nama_sekolah; ?> - Beranda</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <!-- Header --> <header class="header"> <div class="container"> <div class="logo"> <h1><?php echo $nama_sekolah; ?></h1> <p>Berdiri sejak <?php echo $tahun_berdiri; ?></p> </div> <nav class="navbar"> <ul> <li><a href="index.php">Beranda</a></li> <li><a href="about.php">Tentang</a></li> <li><a href="news.php">Berita</a></li> <li><a href="contact.php">Kontak</a></li> </ul> </nav> </div> </header> <!-- Banner Utama --> <section class="hero"> <div class="container"> <h2>Selamat Datang di <?php echo $nama_sekolah; ?></h2> <p>Membentuk generasi cerdas dan berkarakter</p> <a href="about.php" class="btn-primary">Pelajari Lebih Lanjut</a> </div> </section> <!-- Berita Terbaru --> <section class="news-section"> <div class="container"> <h2>Berita Terbaru</h2> <div class="news-grid"> <?php foreach($berita as $item): ?> <div class="news-card"> <h3><?php echo $item['judul']; ?></h3> <p class="date"><?php echo $item['tanggal']; ?></p> <p><?php echo $item['isi']; ?></p> <a href="#" class="read-more">Baca Selengkapnya</a> </div> <?php endforeach; ?> </div> </div> </section> <!-- Footer --> <footer class="footer"> <div class="container"> <p>© 2024 <?php echo $nama_sekolah; ?>. Semua hak dilindungi.</p> <p><?php echo $alamat_sekolah; ?></p> </div> </footer> </body> </html>
Penjelasan Kode:
- <?php ... ?>: Tag untuk menulis kode PHP
- $nama_sekolah: Variabel untuk menyimpan nama sekolah
- $berita = [...]: Array untuk menyimpan data berita
- foreach: Loop untuk menampilkan semua berita
- echo: Perintah untuk menampilkan data
💡 Keuntungan menggunakan PHP:
- Data bisa diubah tanpa edit HTML
- Bisa menampilkan data dari database
- Konten website menjadi dinamis
- Mudah menambah/mengurangi berita
🎨 Membuat File CSS untuk Styling
Mengapa CSS terpisah?
Memisahkan CSS ke file terpisah membuat kode lebih rapi dan mudah dikelola. Satu file CSS bisa digunakan untuk semua halaman website.
/* File: css/style.css */ /* Stylesheet untuk website sekolah */ /* Reset CSS */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Arial', sans-serif; line-height: 1.6; color: #333; } .container { max-width: 1200px; margin: 0 auto; padding: 0 20px; } /* Header Styles */ .header { background: #2c3e50; color: white; padding: 1rem 0; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .header .container { display: flex; justify-content: space-between; align-items: center; } .logo h1 { font-size: 1.8rem; margin-bottom: 0.2rem; } .logo p { font-size: 0.9rem; opacity: 0.8; } /* Navigation */ .navbar ul { display: flex; list-style: none; gap: 2rem; } .navbar a { color: white; text-decoration: none; font-weight: 500; transition: color 0.3s ease; } .navbar a:hover { color: #3498db; } /* Hero Section */ .hero { background: linear-gradient(135deg, #3498db, #2980b9); color: white; padding: 4rem 0; text-align: center; } .hero h2 { font-size: 2.5rem; margin-bottom: 1rem; } .hero p { font-size: 1.2rem; margin-bottom: 2rem; opacity: 0.9; } .btn-primary { background: #e74c3c; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; font-weight: bold; transition: background 0.3s ease; } .btn-primary:hover { background: #c0392b; } /* News Section */ .news-section { padding: 4rem 0; background: #f8f9fa; } .news-section h2 { text-align: center; margin-bottom: 3rem; font-size: 2rem; color: #2c3e50; } .news-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; } .news-card { background: white; padding: 2rem; border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.1); transition: transform 0.3s ease; } .news-card:hover { transform: translateY(-5px); } .news-card h3 { color: #2c3e50; margin-bottom: 0.5rem; } .news-card .date { color: #7f8c8d; font-size: 0.9rem; margin-bottom: 1rem; } .read-more { color: #3498db; text-decoration: none; font-weight: bold; } .read-more:hover { text-decoration: underline; } /* Footer */ .footer { background: #2c3e50; color: white; text-align: center; padding: 2rem 0; } .footer p { margin-bottom: 0.5rem; } /* Responsive Design */ @media (max-width: 768px) { .header .container { flex-direction: column; gap: 1rem; } .navbar ul { gap: 1rem; } .hero h2 { font-size: 2rem; } .news-grid { grid-template-columns: 1fr; } }
Penjelasan CSS:
- * { ... }: Reset CSS untuk menghilangkan margin/padding default
- .container: Class untuk membatasi lebar konten
- flexbox: Untuk layout yang fleksibel
- grid: Untuk layout berita dalam bentuk kartu
- @media: Untuk responsive design (mobile-friendly)
💡 Tips CSS yang baik:
- Gunakan nama class yang deskriptif
- Kelompokkan CSS berdasarkan komponen
- Gunakan komentar untuk menjelaskan bagian penting
- Selalu buat responsive design
🧩 Membuat Komponen yang Dapat Digunakan Ulang
Apa itu komponen?
Komponen adalah bagian website yang bisa digunakan di banyak halaman, seperti header, footer, dan navbar. Dengan membuat komponen terpisah, kita tidak perlu menulis kode yang sama berulang-ulang.
1. Header Component (components/header.php)
<?php // File: components/header.php // Komponen header yang bisa dipakai di semua halaman // Data sekolah (nanti bisa dari database) $site_title = $site_title ?? "SMA Negeri 1 Contoh"; $page_title = $page_title ?? "Beranda"; ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?php echo $site_title . " - " . $page_title; ?></title> <link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/responsive.css"> </head> <body> <header class="header"> <div class="container"> <div class="logo"> <h1><?php echo $site_title; ?></h1> <p>Membentuk Generasi Cerdas</p> </div> <?php include 'components/navbar.php'; ?> </div> </header>
2. Navigation Component (components/navbar.php)
<?php // File: components/navbar.php // Komponen navigasi // Menentukan halaman aktif $current_page = basename($_SERVER['PHP_SELF']); // Menu navigasi $menu_items = [ 'index.php' => 'Beranda', 'about.php' => 'Tentang', 'news.php' => 'Berita', 'gallery.php' => 'Galeri', 'contact.php' => 'Kontak' ]; ?> <nav class="navbar"> <ul> <?php foreach($menu_items as $file => $label): ?> <li> <a href="<?php echo $file; ?>" class="<?php echo ($current_page == $file) ? 'active' : ''; ?>"> <?php echo $label; ?> </a> </li> <?php endforeach; ?> </ul> </nav>
3. Footer Component (components/footer.php)
<?php // File: components/footer.php // Komponen footer $school_info = [ 'name' => 'SMA Negeri 1 Contoh', 'address' => 'Jl. Pendidikan No. 123, Jakarta', 'phone' => '(021) 1234-5678', 'email' => 'info@sman1contoh.sch.id', 'established' => 1985 ]; ?> <footer class="footer"> <div class="container"> <div class="footer-content"> <div class="footer-section"> <h3><?php echo $school_info['name']; ?></h3> <p><?php echo $school_info['address']; ?></p> <p>Telp: <?php echo $school_info['phone']; ?></p> <p>Email: <?php echo $school_info['email']; ?></p> </div> <div class="footer-section"> <h4>Menu Cepat</h4> <ul> <li><a href="index.php">Beranda</a></li> <li><a href="about.php">Tentang Kami</a></li> <li><a href="news.php">Berita</a></li> <li><a href="contact.php">Kontak</a></li> </ul> </div> </div> <div class="footer-bottom"> <p>© <?php echo date('Y'); ?> <?php echo $school_info['name']; ?>. Berdiri sejak <?php echo $school_info['established']; ?></p> </div> </div> </footer> </body> </html>
4. Cara Menggunakan Komponen
<?php // File: about.php // Contoh penggunaan komponen // Set judul halaman $page_title = "Tentang Kami"; // Include header include 'components/header.php'; ?> <main class="main-content"> <section class="about-section"> <div class="container"> <h1>Tentang SMA Negeri 1 Contoh</h1> <p>Sekolah kami berdiri sejak tahun 1985...</p> <div class="stats"> <div class="stat-item"> <h3>1200+</h3> <p>Siswa Aktif</p> </div> <div class="stat-item"> <h3>80+</h3> <p>Guru Berpengalaman</p> </div> <div class="stat-item"> <h3>95%</h3> <p>Tingkat Kelulusan</p> </div> </div> </div> </section> </main> <?php // Include footer include 'components/footer.php'; ?>
Keuntungan menggunakan komponen:
- DRY (Don't Repeat Yourself): Tidak menulis kode yang sama berulang
- Mudah maintenance: Ubah satu file, semua halaman berubah
- Konsistensi: Semua halaman memiliki tampilan yang sama
- Modular: Setiap komponen punya fungsi spesifik
💡 Tips membuat komponen:
- Buat komponen untuk bagian yang sering digunakan
- Gunakan variabel untuk data yang bisa berubah
- Beri nama file yang jelas dan deskriptif
- Dokumentasikan setiap komponen dengan komentar
🗄️ Koneksi Database dan Konfigurasi
Mengapa perlu database?
Database digunakan untuk menyimpan data website seperti berita, profil guru, data siswa, dll. Dengan database, data bisa dikelola dengan mudah tanpa harus edit kode PHP.
1. Konfigurasi Database (config/database.php)
<?php // File: config/database.php // Konfigurasi koneksi database // Pengaturan database define('DB_HOST', 'localhost'); define('DB_NAME', 'sekolah_db'); define('DB_USER', 'root'); define('DB_PASS', ''); // Class untuk koneksi database class Database { private $host = DB_HOST; private $db_name = DB_NAME; private $username = DB_USER; private $password = DB_PASS; private $conn; // Fungsi untuk membuat koneksi public function connect() { $this->conn = null; try { $this->conn = new PDO( "mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password ); $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->conn->exec("set names utf8"); } catch(PDOException $e) { echo "Koneksi gagal: " . $e->getMessage(); } return $this->conn; } } // Fungsi helper untuk mendapatkan koneksi function getConnection() { $database = new Database(); return $database->connect(); } ?>
2. Struktur Database SQL
-- File: database.sql -- Struktur database untuk website sekolah -- Tabel untuk berita/pengumuman CREATE TABLE news ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, author VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, status ENUM('draft', 'published') DEFAULT 'published' ); -- Tabel untuk guru CREATE TABLE teachers ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, subject VARCHAR(100) NOT NULL, education VARCHAR(200), photo VARCHAR(255), bio TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Tabel untuk galeri CREATE TABLE gallery ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, description TEXT, image_path VARCHAR(255) NOT NULL, category ENUM('kegiatan', 'fasilitas', 'prestasi') DEFAULT 'kegiatan', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Tabel untuk pengaturan website CREATE TABLE settings ( id INT AUTO_INCREMENT PRIMARY KEY, setting_key VARCHAR(100) UNIQUE NOT NULL, setting_value TEXT NOT NULL, description VARCHAR(255) ); -- Insert data awal pengaturan INSERT INTO settings (setting_key, setting_value, description) VALUES ('school_name', 'SMA Negeri 1 Contoh', 'Nama sekolah'), ('school_address', 'Jl. Pendidikan No. 123, Jakarta', 'Alamat sekolah'), ('school_phone', '(021) 1234-5678', 'Nomor telepon'), ('school_email', 'info@sman1contoh.sch.id', 'Email sekolah'), ('established_year', '1985', 'Tahun berdiri'); -- Insert contoh data berita INSERT INTO news (title, content, author) VALUES ('Penerimaan Siswa Baru 2024', 'Pendaftaran siswa baru untuk tahun ajaran 2024/2025 telah dibuka. Silakan kunjungi website resmi untuk informasi lebih lanjut.', 'Admin'), ('Prestasi Olimpiade Matematika', 'Siswa kami berhasil meraih juara 1 dalam Olimpiade Matematika tingkat provinsi. Selamat untuk tim yang telah berjuang keras.', 'Admin'); -- Insert contoh data guru INSERT INTO teachers (name, subject, education, bio) VALUES ('Dr. Ahmad Wijaya, S.Pd', 'Matematika', 'S2 Pendidikan Matematika', 'Guru matematika berpengalaman 15 tahun'), ('Siti Nurhaliza, S.S', 'Bahasa Indonesia', 'S1 Sastra Indonesia', 'Guru bahasa Indonesia yang kreatif dan inovatif');
3. Fungsi untuk Mengambil Data (config/functions.php)
<?php // File: config/functions.php // Fungsi-fungsi untuk mengambil data dari database require_once 'database.php'; // Fungsi untuk mengambil pengaturan sekolah function getSchoolSettings() { $conn = getConnection(); $query = "SELECT setting_key, setting_value FROM settings"; $stmt = $conn->prepare($query); $stmt->execute(); $settings = []; while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $settings[$row['setting_key']] = $row['setting_value']; } return $settings; } // Fungsi untuk mengambil berita terbaru function getLatestNews($limit = 5) { $conn = getConnection(); $query = "SELECT * FROM news WHERE status = 'published' ORDER BY created_at DESC LIMIT :limit"; $stmt = $conn->prepare($query); $stmt->bindParam(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } // Fungsi untuk mengambil detail berita function getNewsById($id) { $conn = getConnection(); $query = "SELECT * FROM news WHERE id = :id AND status = 'published'"; $stmt = $conn->prepare($query); $stmt->bindParam(':id', $id, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetch(PDO::FETCH_ASSOC); } // Fungsi untuk mengambil data guru function getAllTeachers() { $conn = getConnection(); $query = "SELECT * FROM teachers ORDER BY name ASC"; $stmt = $conn->prepare($query); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } // Fungsi untuk mengambil galeri function getGalleryByCategory($category = null) { $conn = getConnection(); if($category) { $query = "SELECT * FROM gallery WHERE category = :category ORDER BY created_at DESC"; $stmt = $conn->prepare($query); $stmt->bindParam(':category', $category); } else { $query = "SELECT * FROM gallery ORDER BY created_at DESC"; $stmt = $conn->prepare($query); } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } // Fungsi untuk format tanggal Indonesia function formatTanggal($date) { $bulan = [ 1 => 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember' ]; $timestamp = strtotime($date); $hari = date('d', $timestamp); $bulan_num = date('n', $timestamp); $tahun = date('Y', $timestamp); return $hari . ' ' . $bulan[$bulan_num] . ' ' . $tahun; } ?>
4. Menggunakan Database di Halaman (index.php versi database)
<?php // File: index.php (versi dengan database) require_once 'config/functions.php'; // Ambil data dari database $school_settings = getSchoolSettings(); $latest_news = getLatestNews(3); // Set variabel untuk komponen $page_title = "Beranda"; $site_title = $school_settings['school_name'] ?? "SMA Negeri 1 Contoh"; // Include header include 'components/header.php'; ?> <main class="main-content"> <!-- Hero Section --> <section class="hero"> <div class="container"> <h2>Selamat Datang di <?php echo $site_title; ?></h2> <p>Membentuk generasi cerdas dan berkarakter sejak <?php echo $school_settings['established_year']; ?></p> <a href="about.php" class="btn-primary">Pelajari Lebih Lanjut</a> </div> </section> <!-- Berita Terbaru --> <section class="news-section"> <div class="container"> <h2>Berita Terbaru</h2> <div class="news-grid"> <?php if(!empty($latest_news)): ?> <?php foreach($latest_news as $news): ?> <div class="news-card"> <h3><?php echo htmlspecialchars($news['title']); ?></h3> <p class="date"><?php echo formatTanggal($news['created_at']); ?></p> <p><?php echo substr(strip_tags($news['content']), 0, 150) . '...'; ?></p> <a href="news-detail.php?id=<?php echo $news['id']; ?>" class="read-more"> Baca Selengkapnya </a> </div> <?php endforeach; ?> <?php else: ?> <p>Belum ada berita terbaru.</p> <?php endif; ?> </div> </div> </section> </main> <?php include 'components/footer.php'; ?>
Keuntungan menggunakan database:
- Data terpisah dari kode: Mudah mengelola konten
- Dinamis: Data bisa diubah tanpa edit kode
- Scalable: Bisa menampung banyak data
- Aman: Data tersimpan dengan aman
💡 Tips keamanan database:
- Selalu gunakan prepared statements
- Validasi input dari user
- Gunakan htmlspecialchars() untuk output
- Jangan tampilkan error database ke user
🎉 Tutorial Selesai!
Selamat! Kalian telah berhasil membuat website sekolah dengan PHP
Website yang telah dibuat memiliki struktur yang baik, komponen yang dapat digunakan ulang, dan koneksi database yang aman.
📋 Checklist yang telah dipelajari:
- ✅ Struktur folder yang rapi dan terorganisir
- ✅ File index.php sebagai halaman utama
- ✅ CSS terpisah untuk styling yang konsisten
- ✅ Komponen yang dapat digunakan ulang
- ✅ Koneksi database yang aman
- ✅ Fungsi-fungsi helper untuk data
- ✅ Responsive design untuk mobile
🚀 Langkah selanjutnya untuk pengembangan:
Fitur yang bisa ditambahkan:
- Admin Panel: Untuk mengelola konten website
- Sistem Login: Untuk guru dan siswa
- Upload File: Untuk gambar dan dokumen
- Search Function: Pencarian berita dan konten
- Comment System: Komentar di berita
- Newsletter: Berlangganan berita sekolah
📚 Sumber belajar lanjutan:
Untuk memperdalam PHP:
- Pelajari framework PHP seperti Laravel atau CodeIgniter
- Belajar tentang keamanan web (SQL Injection, XSS)
- Pelajari JavaScript untuk interaksi yang lebih dinamis
- Belajar tentang SEO untuk website
- Pelajari version control dengan Git
📥 Download File Tutorial
Dapatkan semua file source code tutorial ini
💡 Tips untuk siswa:
- Praktikkan setiap langkah secara bertahap
- Jangan takut untuk bereksperimen dengan kode
- Selalu backup file sebelum melakukan perubahan besar
- Bergabung dengan komunitas developer untuk belajar bersama
- Buat project kecil-kecil untuk melatih skill
🔧 Contoh Implementasi Lengkap:
<?php // File: news-detail.php // Halaman detail berita dengan komentar require_once 'config/functions.php'; // Ambil ID berita dari URL $news_id = isset($_GET['id']) ? (int)$_GET['id'] : 0; if($news_id <= 0) { header('Location: news.php'); exit; } // Ambil detail berita $news = getNewsById($news_id); if(!$news) { header('Location: news.php'); exit; } $page_title = $news['title']; include 'components/header.php'; ?> <main class="main-content"> <article class="news-detail"> <div class="container"> <div class="breadcrumb"> <a href="index.php">Beranda</a> > <a href="news.php">Berita</a> > <span><?php echo htmlspecialchars($news['title']); ?></span> </div> <header class="article-header"> <h1><?php echo htmlspecialchars($news['title']); ?></h1> <div class="article-meta"> <span class="author">👤 <?php echo htmlspecialchars($news['author']); ?></span> <span class="date">📅 <?php echo formatTanggal($news['created_at']); ?></span> </div> </header> <div class="article-content"> <?php echo nl2br(htmlspecialchars($news['content'])); ?> </div> <div class="article-actions"> <button onclick="shareArticle()" class="btn-share">📤 Bagikan</button> <button onclick="printArticle()" class="btn-print">🖨️ Cetak</button> </div> </div> </article> </main> <script> function shareArticle() { if (navigator.share) { navigator.share({ title: '<?php echo addslashes($news['title']); ?>', url: window.location.href }); } else { // Fallback untuk browser yang tidak support Web Share API navigator.clipboard.writeText(window.location.href); alert('Link berhasil disalin ke clipboard!'); } } function printArticle() { window.print(); } </script> <?php include 'components/footer.php'; ?>
📱 Responsive CSS Tambahan:
/* File: css/responsive.css */ /* CSS tambahan untuk responsivitas yang lebih baik */ /* Mobile First Approach */ @media (max-width: 480px) { .container { padding: 0 15px; } .hero h2 { font-size: 1.8rem; } .hero p { font-size: 1rem; } .news-card { padding: 1.5rem; } .navbar ul { flex-direction: column; gap: 0.5rem; } .header .container { text-align: center; } } /* Tablet */ @media (min-width: 481px) and (max-width: 768px) { .news-grid { grid-template-columns: repeat(2, 1fr); gap: 1.5rem; } .hero h2 { font-size: 2.2rem; } } /* Desktop */ @media (min-width: 1200px) { .container { max-width: 1400px; } .news-grid { grid-template-columns: repeat(3, 1fr); } } /* Print Styles */ @media print { .header, .footer, .navbar, .article-actions { display: none; } .article-content { font-size: 12pt; line-height: 1.5; } }
⚡ JavaScript Interaktif:
// File: js/script.js // JavaScript untuk interaksi website document.addEventListener('DOMContentLoaded', function() { // Mobile menu toggle const mobileMenuBtn = document.createElement('button'); mobileMenuBtn.innerHTML = '☰'; mobileMenuBtn.className = 'mobile-menu-btn'; mobileMenuBtn.onclick = toggleMobileMenu; const navbar = document.querySelector('.navbar'); if(navbar) { navbar.parentNode.insertBefore(mobileMenuBtn, navbar); } // Smooth scrolling untuk anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if(target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // Loading animation untuk form const forms = document.querySelectorAll('form'); forms.forEach(form => { form.addEventListener('submit', function() { const submitBtn = form.querySelector('button[type="submit"]'); if(submitBtn) { submitBtn.innerHTML = '⏳ Mengirim...'; submitBtn.disabled = true; } }); }); // Auto-hide alerts const alerts = document.querySelectorAll('.alert'); alerts.forEach(alert => { setTimeout(() => { alert.style.opacity = '0'; setTimeout(() => alert.remove(), 300); }, 5000); }); }); function toggleMobileMenu() { const navbar = document.querySelector('.navbar'); navbar.classList.toggle('mobile-active'); } // Search functionality function searchNews() { const searchTerm = document.getElementById('searchInput').value.toLowerCase(); const newsCards = document.querySelectorAll('.news-card'); newsCards.forEach(card => { const title = card.querySelector('h3').textContent.toLowerCase(); const content = card.querySelector('p').textContent.toLowerCase(); if(title.includes(searchTerm) || content.includes(searchTerm)) { card.style.display = 'block'; } else { card.style.display = 'none'; } }); } // Image lazy loading function lazyLoadImages() { const images = document.querySelectorAll('img[data-src]'); const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if(entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.classList.remove('lazy'); imageObserver.unobserve(img); } }); }); images.forEach(img => imageObserver.observe(img)); }
🛡️ Keamanan dan Validasi:
<?php // File: config/security.php // Fungsi keamanan untuk website // Fungsi untuk membersihkan input function cleanInput($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data; } // Fungsi validasi email function validateEmail($email) { return filter_var($email, FILTER_VALIDATE_EMAIL); } // Fungsi untuk generate CSRF token function generateCSRFToken() { if(!isset($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } // Fungsi untuk verifikasi CSRF token function verifyCSRFToken($token) { return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token); } // Fungsi untuk rate limiting function checkRateLimit($action, $limit = 5, $timeframe = 300) { $ip = $_SERVER['REMOTE_ADDR']; $key = $action . '_' . $ip; if(!isset($_SESSION['rate_limit'][$key])) { $_SESSION['rate_limit'][$key] = [ 'count' => 1, 'first_attempt' => time() ]; return true; } $data = $_SESSION['rate_limit'][$key]; // Reset jika sudah melewati timeframe if(time() - $data['first_attempt'] > $timeframe) { $_SESSION['rate_limit'][$key] = [ 'count' => 1, 'first_attempt' => time() ]; return true; } // Cek apakah sudah melebihi limit if($data['count'] >= $limit) { return false; } $_SESSION['rate_limit'][$key]['count']++; return true; } // Fungsi untuk log aktivitas function logActivity($action, $details = '') { $log_file = 'logs/activity.log'; $timestamp = date('Y-m-d H:i:s'); $ip = $_SERVER['REMOTE_ADDR']; $user_agent = $_SERVER['HTTP_USER_AGENT']; $log_entry = "[$timestamp] IP: $ip | Action: $action | Details: $details | User-Agent: $user_agent\n"; file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX); } ?>
🎓 Selamat Belajar!
Semoga tutorial ini bermanfaat untuk perjalanan belajar programming kalian. Terus berlatih dan jangan pernah berhenti belajar!