Environment & Konfigurasi

Di dunia nyata, aplikasi berjalan di dua tempat berbeda: komputer developermu (development) dan server internet (production). Kedua tempat ini butuh konfigurasi yang berbeda — dan konfigurasi sensitif tidak boleh masuk ke Git.

Masalah: Konfigurasi Hardcoded

<?php
// ❌ BAHAYA: Kredensial langsung di kode
$pdo = new PDO(
    "mysql:host=localhost;dbname=toko",
    "root",           // ← Username database
    "password123"     // ← Password database tersebar di Git!
);

Masalah hardcoding:

  1. Beda di setiap environment — password di laptop vs server berbeda
  2. Tercatat di Git — siapapun yang akses repo bisa lihat password
  3. Sulit ganti — harus cari di banyak file jika password berubah
  4. Rawan lupa — developer baru bisa salah config

Solusi: File .env

File .env menyimpan konfigurasi dalam format KUNCI=NILAI, satu per baris:

# .env — File ini TIDAK boleh masuk Git!

# Database
DB_HOST=localhost
DB_NAME=toko_online
DB_USER=root
DB_PASS=password_rahasia

# Aplikasi
APP_ENV=development
APP_URL=http://toko.test
APP_DEBUG=true

# Email (contoh)
MAIL_HOST=smtp.gmail.com
MAIL_USER=[email protected]
MAIL_PASS=abc123xyz

# API Keys
MIDTRANS_KEY=SB-Mid-server-xxx
RAJAONGKIR_KEY=abc123

Baca .env dari PHP

Buat file parser sederhana:

<?php
// config/env.php — Parser file .env

function loadEnv(string $path): void {
    if (!file_exists($path)) {
        return;  // Jangan error — di production mungkin pakai env variable OS
    }

    $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

    foreach ($lines as $line) {
        // Skip komentar
        if (str_starts_with(trim($line), '#')) {
            continue;
        }

        // Parse KUNCI=NILAI
        if (str_contains($line, '=')) {
            [$key, $value] = explode('=', $line, 2);
            $key   = trim($key);
            $value = trim($value);

            // Hapus quotes jika ada
            $value = trim($value, '"\'');

            // Set sebagai environment variable
            $_ENV[$key] = $value;
            putenv("$key=$value");
        }
    }
}

/**
 * Ambil nilai environment variable
 */
function env(string $key, mixed $default = null): mixed {
    $value = $_ENV[$key] ?? getenv($key) ?: $default;

    // Konversi string boolean
    return match(strtolower((string) $value)) {
        'true', '(true)' => true,
        'false', '(false)' => false,
        'null', '(null)' => null,
        default => $value,
    };
}

Gunakan di Konfigurasi Aplikasi

<?php
// config/app.php — Konfigurasi aplikasi

require_once __DIR__ . '/env.php';

// Load file .env dari root project
loadEnv(__DIR__ . '/../.env');

// Konfigurasi menggunakan env()
define('APP_ENV', env('APP_ENV', 'production'));
define('APP_URL', env('APP_URL', 'http://localhost'));
define('APP_DEBUG', env('APP_DEBUG', false));

// Environment: development or production
if (APP_DEBUG) {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
} else {
    error_reporting(E_ALL);
    ini_set('display_errors', '0');
    ini_set('log_errors', '1');
    ini_set('error_log', __DIR__ . '/../logs/php-error.log');
}
<?php
// config/database.php — Koneksi database menggunakan env()

require_once __DIR__ . '/app.php';

$host = env('DB_HOST', 'localhost');
$name = env('DB_NAME', 'toko');
$user = env('DB_USER', 'root');
$pass = env('DB_PASS', '');

try {
    $pdo = new PDO(
        "mysql:host=$host;dbname=$name;charset=utf8mb4",
        $user,
        $pass,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]
    );
} catch (PDOException $e) {
    if (APP_DEBUG) {
        die("Koneksi gagal: " . $e->getMessage());
    } else {
        error_log("Database error: " . $e->getMessage());
        die("Maaf, sistem sedang mengalami gangguan.");
    }
}

.env.example — Template untuk Tim

Buat file contoh (tanpa nilai sensitif) yang masuk Git:

# .env.example — Copy file ini ke .env dan isi nilainya

DB_HOST=localhost
DB_NAME=toko_online
DB_USER=root
DB_PASS=

APP_ENV=development
APP_URL=http://toko.test
APP_DEBUG=true

MAIL_HOST=
MAIL_USER=
MAIL_PASS=

.gitignore — Lindungi File Sensitif

# ⚠️ WAJIB: Jangan pernah commit file .env
.env

# Boleh commit (ini hanya template tanpa password)
# .env.example

# Log files
logs/*.log

Development vs Production

AspekDevelopmentProduction
APP_ENVdevelopmentproduction
APP_DEBUGtruefalse
display_errors1 (tampilkan)0 (sembunyikan)
DB_HOSTlocalhostdb.server.com
DB_PASSroot / kosongPassword kuat & unik
Error handlingTampilkan detailLog ke file, tampilkan pesan ramah
HTTPSOpsionalWajib
Session cookieDefaultsecure, httponly, samesite

Contoh: Perilaku Berbeda per Environment

<?php
// Tampilkan debug bar hanya di development
if (APP_ENV === 'development') {
    echo "<!-- Debug: Query count = $queryCount, Time = {$executionTime}ms -->";
}

// Email: kirim asli hanya di production
if (APP_ENV === 'production') {
    mail($to, $subject, $body);
} else {
    // Di development, simpan ke file saja
    file_put_contents('logs/email.log', "$to | $subject | $body\n", FILE_APPEND);
    echo "📧 Email log disimpan (dev mode)";
}

Keamanan Konfigurasi

WARNING
  1. ✅ File .env tidak boleh masuk Git (ada di .gitignore)
  2. ✅ Gunakan .env.example sebagai template (tanpa nilai sensitif)
  3. ✅ Jangan hardcode password di kode PHP
  4. ✅ Development: APP_DEBUG=true, Production: APP_DEBUG=false
  5. ✅ Set display_errors=0 di production
  6. ✅ Gunakan password database yang kuat dan unik per environment
  7. ✅ API keys dan secret tokens simpan di .env, bukan di kode

Variadic Config (Opsional: Config Array)

Untuk aplikasi yang lebih besar, kelompokkan konfigurasi:

<?php
// config/config.php — Konfigurasi terpusat

return [
    'app' => [
        'name' => env('APP_NAME', 'Toko Online'),
        'env'  => env('APP_ENV', 'production'),
        'url'  => env('APP_URL', 'http://localhost'),
        'debug' => env('APP_DEBUG', false),
    ],
    'database' => [
        'host' => env('DB_HOST', 'localhost'),
        'name' => env('DB_NAME', 'toko'),
        'user' => env('DB_USER', 'root'),
        'pass' => env('DB_PASS', ''),
    ],
    'mail' => [
        'host' => env('MAIL_HOST', 'smtp.gmail.com'),
        'port' => env('MAIL_PORT', 587),
        'user' => env('MAIL_USER', ''),
        'pass' => env('MAIL_PASS', ''),
    ],
];
<?php
// Penggunaan
$config = require __DIR__ . '/config.php';
echo $config['app']['name'];  // "Toko Online"
echo $config['database']['host'];  // "localhost"
NOTE
  • File .env di root project
  • Fungsi env() dan config() bawaan
  • Config files di folder config/ (database.php, mail.php, dll)
  • Library vlucas/phpdotenv untuk parsing .env

Kamu sudah belajar fondasinya!

Latihan

  1. Buat file .env dan .env.example di root project Toko Online
  2. Pindahkan semua hardcoded credentials ke .env
  3. Tambahkan .env ke .gitignore
  4. Buat config/app.php yang load .env dan set error reporting berdasarkan environment
  5. Test: ubah APP_DEBUG=false lalu buat sengaja error — pastikan error tidak tampil di browser

Penutup

Dengan semua materi di Phase 5 ini, kamu sudah memiliki fondasi profesional untuk membangun aplikasi PHP yang:

  • 🔐 Aman — password di-hash, input divalidasi, role-based access
  • 🏗️ Terstruktur — front controller, routing, config terpisah
  • 🆕 Modern — PHP 8.x features, type safety, immutable objects
  • 🚀 Siap production — environment config, error handling yang proper

Lanjut ke Interface & Abstract Class → untuk mulai Phase 6: OOP Lanjutan sebelum masuk ke ekosistem Laravel! 🌉