Back to Blog Backend PHP

Membangun MVC PHP dari Awal

app/Controllers/Models/Views/public/index.phproutes/web.php

MVC memisahkan penerimaan request, aturan aplikasi, dan tampilan. Tujuannya bukan membuat folder terlihat rapi, tetapi mencegah SQL, HTML, dan logika bisnis bercampur dalam satu file.

Front controller sebagai pintu masuk

PHP
<?php
// public/index.php
require dirname(__DIR__).'/vendor/autoload.php';
$container = require dirname(__DIR__).'/bootstrap.php';
$router = $container->get(Router::class);
$response = $router->dispatch($_SERVER['REQUEST_METHOD'], parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$response->send();

Router memetakan request ke controller

PHP
$router->get('/products', [ProductController::class, 'index']);
$router->post('/products', [ProductController::class, 'store']);
$router->get('/products/{id}', [ProductController::class, 'show']);

Controller tetap tipis

PHP
final class ProductController
{
    public function __construct(private ProductService $products) {}
    public function store(Request $request): Response
    {
        $input = CreateProductData::fromArray($request->all());
        $product = $this->products->create($input);
        return Response::redirect('/products/'.$product->id);
    }
}

Validasi bentuk input dapat dilakukan oleh data object, sedangkan aturan bisnis berada di service/domain. Controller hanya menerjemahkan HTTP ke operasi aplikasi.

Model bukan sinonim tabel

Model mewakili data dan aturan domain. Akses database dapat dipisahkan ke repository agar model tidak bergantung langsung pada PDO.

PHP
final class PdoProductRepository implements ProductRepository
{
    public function find(int $id): ?Product
    {
        $stmt = $this->pdo->prepare('SELECT * FROM products WHERE id = :id');
        $stmt->execute(['id' => $id]);
        $row = $stmt->fetch();
        return $row ? Product::fromRow($row) : null;
    }
}

Urutan implementasi yang efektif

  1. 1
    Bangun Request dan Response kecil.
  2. 2
    Tambahkan router dengan parameter URL.
  3. 3
    Buat satu feature end-to-end: route, controller, service, repository, view.
  4. 4
    Tambahkan error handler dan middleware.
  5. 5
    Tulis integration test sebelum menambah feature berikutnya.
Share this article

Related articles

Copied