Panduan komprehensif untuk setup PHP website/aplikasi, dari template hingga siap production di server.
# 1. Download XAMPP dari https://www.apachefriends.org
# 2. Install dengan default settings
# 3. Start Apache & MySQL dari XAMPP Control Panel
# 4. Akses http://localhost
# 1. Download MAMP dari https://www.mamp.info
# 2. Install aplikasi
# 3. Klik Start Servers
# 4. Akses http://localhost:8888
# Install Apache
sudo apt-get update
sudo apt-get install apache2
# Install PHP
sudo apt-get install php php-cli php-mysql php-curl php-gd php-mbstring
# Install MySQL
sudo apt-get install mysql-server
# Start services
sudo systemctl start apache2
sudo systemctl start mysql
# File: docker-compose.yml
version: '3.8'
services:
php:
image: php:8.1-apache
ports:
- "80:80"
volumes:
- ./:/var/www/html
environment:
DB_HOST: db
DB_USER: root
DB_PASSWORD: password
DB_NAME: phpdb
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: phpdb
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
docker-compose up -d
1. PHPFOX, PHP Scripts
2. Marketplace Premium
3. GitHub
git clone repo-url4. CMS Populer (jika ingin pakai CMS)
# Extract template
unzip php-template.zip
# Copy ke folder web server
# Windows XAMPP: C:\xampp\htdocs\project
# macOS MAMP: /Applications/MAMP/htdocs/project
# Linux: /var/www/html/project
# Set permissions (Linux/Mac)
chmod -R 755 .
chmod -R 777 uploads storage cache
project/
├── index.php # Entry point
├── config.php # Configuration
│
├── public/
│ ├── index.php # Public entry
│ ├── .htaccess # Apache routing
│ ├── css/
│ ├── js/
│ └── images/
│
├── app/
│ ├── controllers/ # Business logic
│ ├── models/ # Database models
│ ├── views/ # View templates
│ └── helpers/ # Helper functions
│
├── database/
│ ├── config.php # Database connection
│ ├── migrations/ # Schema files
│ └── seeds/ # Sample data
│
├── includes/
│ ├── header.php
│ ├── footer.php
│ └── sidebar.php
│
├── admin/ # Admin panel
│ ├── index.php
│ ├── css/
│ └── js/
│
├── uploads/ # User uploads
├── logs/ # Error logs
│
├── .htaccess # URL rewriting
├── config.php # Main config
└── README.md
Create database/config.php atau edit yang sudah ada:
<?php
// Database configuration
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASSWORD', 'password');
define('DB_NAME', 'project_db');
// Create connection
$conn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Set charset
$conn->set_charset("utf8");
?>
# Login ke MySQL
mysql -u root -p
# Buat database
CREATE DATABASE project_db;
USE project_db;
# Buat table (contoh users table)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
# Insert sample data
INSERT INTO users (username, email, password) VALUES
('admin', 'admin@example.com', MD5('password123'));
EXIT;
Atau jalankan file SQL jika template sudah punya:
mysql -u root -p project_db < database/schema.sql
<?php
// index.php
session_start();
// Include configuration
require_once 'database/config.php';
require_once 'app/helpers/functions.php';
// Determine page
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
// Security: Sanitize input
$page = preg_replace('/[^a-zA-Z0-9_]/', '', $page);
// Check if page exists
if (file_exists("app/views/{$page}.php")) {
require "includes/header.php";
require "app/views/{$page}.php";
require "includes/footer.php";
} else {
require "includes/header.php";
require "app/views/404.php";
require "includes/footer.php";
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo isset($page_title) ? $page_title : 'Website'; ?></title>
<link rel="stylesheet" href="public/css/style.css">
</head>
<body>
<header>
<nav>
<ul>
<li><a href="index.php?page=home">Home</a></li>
<li><a href="index.php?page=about">About</a></li>
<li><a href="index.php?page=services">Services</a></li>
<li><a href="index.php?page=contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
</main>
<footer>
<p>© <?php echo date('Y'); ?> Website Saya</p>
</footer>
<script src="public/js/main.js"></script>
</body>
</html>
<?php
require 'database/config.php';
// SELECT - Get data
$query = "SELECT * FROM users";
$result = $conn->query($query);
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "ID: " . $row['id'] . " - Name: " . $row['username'];
}
} else {
echo "No results found";
}
// INSERT - Add data
$username = $_POST['username'] ?? '';
$email = $_POST['email'] ?? '';
$password = password_hash($_POST['password'] ?? '', PASSWORD_DEFAULT);
if (!empty($username) && !empty($email) && !empty($password)) {
$insert_query = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";
$stmt = $conn->prepare($insert_query);
$stmt->bind_param("sss", $username, $email, $password);
if ($stmt->execute()) {
echo "User created successfully";
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
}
// UPDATE - Edit data
$id = $_POST['id'] ?? 0;
$username = $_POST['username'] ?? '';
if ($id > 0) {
$update_query = "UPDATE users SET username = ? WHERE id = ?";
$stmt = $conn->prepare($update_query);
$stmt->bind_param("si", $username, $id);
if ($stmt->execute()) {
echo "User updated";
}
$stmt->close();
}
// DELETE - Remove data
$id = $_GET['id'] ?? 0;
if ($id > 0) {
$delete_query = "DELETE FROM users WHERE id = ?";
$stmt = $conn->prepare($delete_query);
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
echo "User deleted";
}
$stmt->close();
}
?>
<?php
// app/controllers/form.php
$errors = [];
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize input
$name = htmlspecialchars($_POST['name'] ?? '');
$email = filter_var($_POST['email'] ?? '', FILTER_SANITIZE_EMAIL);
$message = htmlspecialchars($_POST['message'] ?? '');
// Validate
if (empty($name)) $errors[] = "Nama wajib diisi";
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Email tidak valid";
}
if (empty($message)) $errors[] = "Pesan wajib diisi";
// Process jika valid
if (empty($errors)) {
// Save to database atau kirim email
$insert = "INSERT INTO messages (name, email, message) VALUES (?, ?, ?)";
$stmt = $conn->prepare($insert);
$stmt->bind_param("sss", $name, $email, $message);
if ($stmt->execute()) {
$success = true;
}
$stmt->close();
}
}
?>
<!-- View -->
<?php if ($success): ?>
<div class="alert success">Pesan berhasil dikirim!</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="alert error">
<?php foreach ($errors as $error): ?>
<p><?php echo $error; ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<form method="POST">
<input type="text" name="name" placeholder="Nama Anda" value="<?php echo $name ?? ''; ?>">
<input type="email" name="email" placeholder="Email" value="<?php echo $email ?? ''; ?>">
<textarea name="message"><?php echo $message ?? ''; ?></textarea>
<button type="submit">Kirim</button>
</form>
<?php
// app/controllers/login.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (!empty($username) && !empty($password)) {
// Check database
$query = "SELECT id, username, password FROM users WHERE username = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 1) {
$user = $result->fetch_assoc();
// Verify password
if (password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
header("Location: dashboard.php");
exit;
}
}
$error = "Username atau password salah";
}
}
?>
<?php
// Check if user logged in
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
?>
<?php
session_start();
session_destroy();
header("Location: index.php");
exit;
?>
<?php
// api/users.php
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
$id = $_GET['id'] ?? null;
require_once '../database/config.php';
switch ($method) {
case 'GET':
if ($id) {
// GET single user
$query = "SELECT * FROM users WHERE id = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $id);
} else {
// GET all users
$query = "SELECT * FROM users";
$stmt = $conn->prepare($query);
}
$stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_all(MYSQLI_ASSOC);
echo json_encode(['status' => 'success', 'data' => $data]);
break;
case 'POST':
// CREATE user
$data = json_decode(file_get_contents('php://input'), true);
$query = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $data['username'], $data['email'],
password_hash($data['password'], PASSWORD_DEFAULT));
if ($stmt->execute()) {
echo json_encode(['status' => 'success', 'id' => $conn->insert_id]);
} else {
echo json_encode(['status' => 'error', 'message' => $stmt->error]);
}
break;
case 'PUT':
// UPDATE user
$data = json_decode(file_get_contents('php://input'), true);
$query = "UPDATE users SET username = ? WHERE id = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param("si", $data['username'], $id);
if ($stmt->execute()) {
echo json_encode(['status' => 'success']);
} else {
echo json_encode(['status' => 'error', 'message' => $stmt->error]);
}
break;
case 'DELETE':
// DELETE user
$query = "DELETE FROM users WHERE id = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
echo json_encode(['status' => 'success']);
} else {
echo json_encode(['status' => 'error', 'message' => $stmt->error]);
}
break;
}
?>
// ✗ TIDAK AMAN - SQL Injection risk
$query = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'";
// ✓ AMAN - Prepared statements
$query = "SELECT * FROM users WHERE username = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
// ✗ TIDAK AMAN
echo "Welcome " . $_GET['name'];
// ✓ AMAN - Escape output
echo "Welcome " . htmlspecialchars($_GET['name']);
// Generate token
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// Add to form
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
// Verify token
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("CSRF token mismatch");
}
// Hash password
$password = password_hash($_POST['password'], PASSWORD_BCRYPT);
// Verify password
if (password_verify($_POST['password'], $hashed_password)) {
// Password correct
}
# 1. FTP ke server
# 2. Upload semua files ke public_html
# 3. Upload database dump via phpMyAdmin
# 4. Edit config.php dengan database credentials production
# 5. Set folder permissions: chmod 755 folders, 644 files
# 6. Website live
# SSH ke server
ssh root@server_ip
# Install dependencies
apt-get update
apt-get install apache2 php-8.1 php-mysql mysql-server
# Clone repository
cd /var/www
git clone your-repo-url project
# Setup database
mysql -u root -p < project/database/schema.sql
# Set permissions
chmod -R 755 project/
chmod -R 777 project/uploads project/cache project/logs
# Enable mod_rewrite untuk .htaccess
a2enmod rewrite
systemctl restart apache2
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Remove .php extension
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?page=$1 [QSA,L]
</IfModule>
<?php
// Simple file-based caching
$cache_file = 'cache/' . md5($_SERVER['REQUEST_URI']) . '.cache';
$cache_time = 3600; // 1 hour
if (file_exists($cache_file) && time() - filemtime($cache_file) < $cache_time) {
readfile($cache_file);
exit;
}
// Generate content
ob_start();
// Your content here
// Save to cache
$content = ob_get_clean();
file_put_contents($cache_file, $content);
echo $content;
?>
// Add indexes
CREATE INDEX idx_username ON users(username);
CREATE INDEX idx_email ON users(email);
session_start() called at topa2enmod rewritesystemctl restart apache2Resources: