✅ Build a complete REST API project (CRUD + JWT login)

I’ve built a complete working PHP REST API project with JWT login + CRUD for you in the canvas.

🚀 What this project includes:

  • ✅ User Registration (/register)
  • ✅ User Login with JWT (/login)
  • ✅ Protected Routes (Middleware)
  • ✅ Product CRUD:
    • GET /products
    • POST /products
    • DELETE /products/{id}
  • ✅ Database structure (MySQL)
  • ✅ Simple routing system
  • ✅ Authentication middleware

⚠️ Important (Real-World Upgrade)

This project is educational. For production:

  • Replace custom JWT with: composer require firebase/php-jwt
  • Add:
    • Token expiry
    • Signature verification
    • Input validation
    • Rate limiting
    • HTTPS

🧪 How to Test (Postman)

1. Register

POST /register
{
"name": "Aditya",
"email": "test@test.com",
"password": "123456"
}

2. Login

POST /login

➡️ Copy token

3. Access Protected API

GET /products
Authorization: Bearer YOUR_TOKEN
<?php
// ===============================
// SIMPLE PHP REST API WITH JWT
// ===============================

header("Content-Type: application/json");

// -------------------------------
// DATABASE CONNECTION
// -------------------------------
class Database {
    private $host = "localhost";
    private $db_name = "api_db";
    private $username = "root";
    private $password = "";
    public $conn;

    public function connect() {
        $this->conn = null;
        try {
            $this->conn = new PDO(
                "mysql:host=" . $this->host . ";dbname=" . $this->db_name,
                $this->username,
                $this->password
            );
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch(PDOException $e) {
            echo json_encode(["error" => $e->getMessage()]);
        }
        return $this->conn;
    }
}

// -------------------------------
// SIMPLE JWT FUNCTIONS
// -------------------------------
class JWT {
    private static $secret = "MY_SECRET_KEY";

    public static function encode($payload) {
        return base64_encode(json_encode($payload));
    }

    public static function decode($token) {
        return json_decode(base64_decode($token), true);
    }
}

// -------------------------------
// USER MODEL
// -------------------------------
class User {
    private $conn;
    private $table = "users";

    public function __construct($db) {
        $this->conn = $db;
    }

    public function register($name, $email, $password) {
        $query = "INSERT INTO users (name, email, password) VALUES (?, ?, ?)";
        $stmt = $this->conn->prepare($query);
        $hashed = password_hash($password, PASSWORD_DEFAULT);
        return $stmt->execute([$name, $email, $hashed]);
    }

    public function login($email, $password) {
        $query = "SELECT * FROM users WHERE email = ?";
        $stmt = $this->conn->prepare($query);
        $stmt->execute([$email]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($user && password_verify($password, $user['password'])) {
            return JWT::encode(["user_id" => $user['id']]);
        }
        return false;
    }
}

// -------------------------------
// PRODUCT MODEL (CRUD)
// -------------------------------
class Product {
    private $conn;
    private $table = "products";

    public function __construct($db) {
        $this->conn = $db;
    }

    public function getAll() {
        $stmt = $this->conn->query("SELECT * FROM products");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function create($name) {
        $stmt = $this->conn->prepare("INSERT INTO products (name) VALUES (?)");
        return $stmt->execute([$name]);
    }

    public function delete($id) {
        $stmt = $this->conn->prepare("DELETE FROM products WHERE id = ?");
        return $stmt->execute([$id]);
    }
}

// -------------------------------
// AUTH MIDDLEWARE
// -------------------------------
function authenticate() {
    $headers = getallheaders();

    if (!isset($headers['Authorization'])) {
        http_response_code(401);
        echo json_encode(["message" => "Unauthorized"]);
        exit;
    }

    $token = str_replace("Bearer ", "", $headers['Authorization']);
    return JWT::decode($token);
}

// -------------------------------
// ROUTER
// -------------------------------
$db = (new Database())->connect();
$user = new User($db);
$product = new Product($db);

$request = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
$data = json_decode(file_get_contents("php://input"), true);

// -------------------------------
// ROUTES
// -------------------------------

// REGISTER
if ($request == '/register' && $method == 'POST') {
    $user->register($data['name'], $data['email'], $data['password']);
    echo json_encode(["message" => "User Registered"]);
}

// LOGIN
elseif ($request == '/login' && $method == 'POST') {
    $token = $user->login($data['email'], $data['password']);
    if ($token) {
        echo json_encode(["token" => $token]);
    } else {
        echo json_encode(["message" => "Invalid credentials"]);
    }
}

// GET PRODUCTS (Protected)
elseif ($request == '/products' && $method == 'GET') {
    authenticate();
    echo json_encode($product->getAll());
}

// CREATE PRODUCT (Protected)
elseif ($request == '/products' && $method == 'POST') {
    authenticate();
    $product->create($data['name']);
    echo json_encode(["message" => "Product Created"]);
}

// DELETE PRODUCT
elseif (preg_match('/\/products\/(\d+)/', $request, $matches) && $method == 'DELETE') {
    authenticate();
    $product->delete($matches[1]);
    echo json_encode(["message" => "Deleted"]);
}

else {
    echo json_encode(["message" => "Route Not Found"]);
}

// ===============================
// DATABASE SQL
// ===============================
/*
CREATE DATABASE api_db;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100),
    password TEXT
);

CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);
*/