Selamat datang di part 54 seri tutorial pemrograman PHP! Di part ini, kita akan menyelami dunia microservices architecture. Microservices adalah pendekatan arsitektur di mana aplikasi dibangun sebagai kumpulan layanan kecil yang independen, dikomunikasikan melalui API. Ini adalah topik advanced, tetapi pemahaman tentang ini sangat penting untuk membangun aplikasi yang scalable, maintainable, dan resilient. Sebagai prasyarat, Anda diharapkan sudah familiar dengan konsep dasar PHP, REST APIs, dan idealnya sudah memahami konsep Message Broker seperti RabbitMQ (seperti yang dibahas di Tutorial Pemrograman Part sebelumnya). Jika belum, sangat disarankan untuk membacanya terlebih dahulu.
Bayangkan Anda memiliki toko serba ada yang besar. Pendekatan monolithic (semua dalam satu) adalah seperti semua karyawan toko melakukan semua pekerjaan – mulai dari memesan barang, melayani pelanggan, membersihkan toko, hingga menghitung keuangan. Jika satu orang sakit atau satu sistem rusak, seluruh toko terpengaruh.
Microservices adalah seperti membagi toko menjadi departemen-departemen kecil yang independen: departemen makanan, departemen pakaian, departemen elektronik. Setiap departemen memiliki karyawan sendiri, beroperasi secara independen, dan berkomunikasi dengan departemen lain jika diperlukan (misalnya, departemen makanan perlu tahu apakah inventarisnya mencukupi dari sistem inventaris terpusat). Jika departemen pakaian mengalami masalah, departemen makanan tetap bisa beroperasi. Inilah esensi dari resilience dan scalability.
Mari kita buat contoh sederhana dengan dua microservices: UserService dan ProductService. UserService akan mengelola data pengguna, dan ProductService akan mengelola data produk. Keduanya akan berkomunikasi melalui REST API.
Buat folder user-service dan file index.php:
<?php
require_once 'vendor/autoload.php'; // Jika menggunakan Composer
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
// Inisialisasi Router
$routes = new RouteCollection();
$routes->add('user_get', new Route('/users/{id}', ['_controller' => 'UserService::getUser']));
class UserService {
public function getUser(Request $request) {
$userId = $request->attributes->get('id');
// Simulasi data pengguna
$users = [
1 => ['id' => 1, 'name' => 'John Doe', 'email' => 'john.doe@example.com'],
2 => ['id' => 2, 'name' => 'Jane Doe', 'email' => 'jane.doe@example.com'],
];
if (isset($users[$userId])) {
$user = $users[$userId];
$response = new Response(json_encode($user), 200, ['Content-Type' => 'application/json']);
} else {
$response = new Response(json_encode(['message' => 'User not found']), 404, ['Content-Type' => 'application/json']);
}
return $response;
}
}
$request = Request::createFromGlobals();
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($routes, $context);
$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();
try {
$parameters = $matcher->match($request->getPathInfo());
$request->attributes->add($parameters);
$controller = $controllerResolver->getController($request);
$arguments = $argumentResolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $exception) {
$response = new Response('Not Found', 404);
} catch (Exception $exception) {
$response = new Response('An error occurred', 500);
}
$response->send();
Buat folder product-service dan file index.php:
<?php
require_once 'vendor/autoload.php'; // Jika menggunakan Composer
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
// Inisialisasi Router
$routes = new RouteCollection();
$routes->add('product_get', new Route('/products/{id}', ['_controller' => 'ProductService::getProduct']));
class ProductService {
public function getProduct(Request $request) {
$productId = $request->attributes->get('id');
// Simulasi data produk
$products = [
1 => ['id' => 1, 'name' => 'Laptop', 'price' => 1200],
2 => ['id' => 2, 'name' => 'Smartphone', 'price' => 800],
];
if (isset($products[$productId])) {
$product = $products[$productId];
$response = new Response(json_encode($product), 200, ['Content-Type' => 'application/json']);
} else {
$response = new Response(json_encode(['message' => 'Product not found']), 404, ['Content-Type' => 'application/json']);
}
return $response;
}
}
$request = Request::createFromGlobals();
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($routes, $context);
$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();
try {
$parameters = $matcher->match($request->getPathInfo());
$request->attributes->add($parameters);
$controller = $controllerResolver->getController($request);
$arguments = $argumentResolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $exception) {
$response = new Response('Not Found', 404);
} catch (Exception $exception) {
$response = new Response('An error occurred', 500);
}
$response->send();
Penjelasan Kode:
/users/{id} atau /products/{id} untuk mengambil data berdasarkan ID.Cara Menjalankan:
composer require symfony/routing symfony/http-foundation symfony/http-kernel di masing-masing direktori user-service dan product-service.php -S localhost:8000 untuk UserService dan php -S localhost:8001 untuk ProductService).http://localhost:8000/users/1 atau http://localhost:8001/products/2 untuk melihat data.Coba tambahkan endpoint baru ke ProductService untuk membuat produk baru (POST /products). Gunakan file_put_contents untuk menyimpan data produk ke dalam file JSON (jangan gunakan database sungguhan untuk challenge ini).