Pretty URL, Routing ও API Consume

লেসন ৩৯ / ৩৯

Pretty URL (.htaccess)

# api/.htaccess
RewriteEngine On
RewriteBase /api/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [QSA,L]

Router (index.php)

<?php
header("Content-Type: application/json; charset=utf-8");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") exit;

require "config/db.php";
require "helpers/jwt.php";
require "helpers/auth.php";

$route = $_GET["route"] ?? "";
$parts = explode("/", trim($route, "/"));
$resource = $parts[0] ?? "";
$id = isset($parts[1]) ? (int)$parts[1] : 0;
$method = $_SERVER["REQUEST_METHOD"];
$conn = DB::get();

switch ($resource) {
    case "products":
        require "routes/products.php";
        handleProducts($conn, $method, $id);
        break;
    case "auth":
        $action = $parts[1] ?? "";
        require "routes/auth.php";
        handleAuth($conn, $method, $action);
        break;
    case "profile":
        require "routes/profile.php";
        handleProfile($conn, $method);
        break;
    default:
        respond(404, ["error" => "Endpoint পাওয়া যায়নি"]);
}
?>

URL Examples

GET    /api/products              → সব
GET    /api/products/5             → id=5
POST   /api/products              → তৈরি
PUT    /api/products/5             → update
DELETE /api/products/5             → মুছে

POST   /api/auth/register
POST   /api/auth/login
GET    /api/profile                → current user

Folder Structure

api/
├── .htaccess
├── index.php
├── config/db.php
├── helpers/
│   ├── response.php
│   ├── jwt.php
│   └── auth.php
└── routes/
    ├── products.php
    ├── auth.php
    └── profile.php

API Testing Tools

  • Postman — GUI, সবচেয়ে জনপ্রিয়
  • Thunder Client — VS Code extension
  • Insomnia — open-source
  • curl — command line

PHP থেকে API Call (cURL)

<?php
// GET
$ch = curl_init("https://api.github.com/users/torvalds");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => "MyApp/1.0"
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);

// POST
$ch = curl_init("https://api.example.com/users");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(["name" => "করিম"]),
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "Authorization: Bearer TOKEN"
    ]
]);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
?>

Reusable API Client

<?php
class ApiClient {
    public function __construct(
        private string $baseUrl,
        private ?string $token = null
    ) {}

    public function get(string $path, array $params = []): array {
        $url = $this->baseUrl . $path;
        if ($params) $url .= "?" . http_build_query($params);
        return $this->request("GET", $url);
    }

    public function post(string $path, array $data): array {
        return $this->request("POST", $this->baseUrl . $path, $data);
    }

    public function put(string $path, array $data): array {
        return $this->request("PUT", $this->baseUrl . $path, $data);
    }

    public function delete(string $path): array {
        return $this->request("DELETE", $this->baseUrl . $path);
    }

    private function request(string $method, string $url, ?array $data = null): array {
        $ch = curl_init($url);
        $headers = ["Content-Type: application/json"];
        if ($this->token) $headers[] = "Authorization: Bearer {$this->token}";

        $opts = [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_TIMEOUT => 30
        ];
        if ($data !== null) $opts[CURLOPT_POSTFIELDS] = json_encode($data);

        curl_setopt_array($ch, $opts);
        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return ["status" => $code, "data" => json_decode($response, true)];
    }
}

// ব্যবহার
$api = new ApiClient("http://localhost/api", "TOKEN");
$products = $api->get("/products", ["limit" => 10]);
$new = $api->post("/products", ["name" => "কলম", "price" => 50]);
$api->delete("/products/5");
?>

JavaScript — fetch

// Reusable
async function apiCall(method, path, data = null) {
    const token = localStorage.getItem("token");
    const options = {
        method,
        headers: {
            "Content-Type": "application/json",
            ...(token && { "Authorization": `Bearer ${token}` })
        }
    };
    if (data) options.body = JSON.stringify(data);

    const res = await fetch(`/api${path}`, options);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
}

// ব্যবহার
const products = await apiCall("GET", "/products");
await apiCall("POST", "/products", { name: "কলম", price: 50 });

// Login flow
const result = await apiCall("POST", "/auth/login", {
    email: "k@mail.com",
    password: "secret"
});
localStorage.setItem("token", result.data.token);

🎉 অভিনন্দন!

আপনি এখন OOP, PHP, MySQL, API তৈরি ও consume — সবই জানেন। পরের ধাপ: Laravel/Symfony framework, TDD, Docker, CI/CD।