Mastering REST API Development with PHP: A Comprehensive Tutorial

Mastering REST API Development with PHP: A Comprehensive Tutorial

Introduction

REST (Representational State Transfer) is a style of software architecture that provides a standard for creating web services. RESTful web services are those that follow the REST principles. A RESTful web service provides an API (Application Programming Interface) that enables the communication between different systems.

In this tutorial, we will create a RESTful API using PHP. We will use the Slim framework, which is a micro-framework for creating web applications and APIs.

Prerequisites

Before starting this tutorial, make sure that you have the following installed on your system:

  • PHP 7.0 or higher

  • Composer

  • A web server (e.g. Apache)

Step 1: Install Slim Framework

We will use Composer to install the Slim framework. Create a new directory for your project and run the following command in the terminal:

composer require slim/slim "^4.0"

This will install the latest version of the Slim framework.

Step 2: Create the Project Structure

Create the following directories in your project directory:

  • app: This directory will contain the application code.

  • public: This directory will contain the public files of the application, such as the index.php file.

  • vendor: This directory will contain the dependencies installed by Composer.

Create the following files in the project directory:

  • .htaccess: This file will be used to rewrite URLs for Apache.

  • index.php: This file will be the entry point of our application.

The .htaccess file should contain the following code:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

This will redirect all requests to the index.php file.

The index.php file should contain the following code:

<?php
require __DIR__ . '/../vendor/autoload.php';

use Slim\Factory\AppFactory;

$app = AppFactory::create();

$app->run();
?>

This will create an instance of the Slim application and start the application.

Step 3: Define the Routes

Now we will define the routes for our API. In this tutorial, we will create an API for managing books. The API will have the following routes:

  • GET /books: Get all books.

  • GET /books/{id}: Get a book by ID.

  • POST /books: Create a new book.

  • PUT /books/{id}: Update a book by ID.

  • DELETE /books/{id}: Delete a book by ID.

Create a new directory app in the project directory. Create the following files in the app directory:

  • config.php: This file will contain the configuration for the database.

  • Book.php: This file will contain the model for the book.

  • BookController.php: This file will contain the controller for the book.

The config.php file should contain the following code:

<?php

return [
    'db' => [
        'host' => 'localhost',
        'user' => 'root',
        'password' => 'password',
        'database' => 'books'
    ]
];
?>

Replace the values of the host, user, password, and database keys with your database configuration.

The Book.php file should contain the following code:

<?php

namespace App;

use PDO;

class Book
{
    private $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function getAll()
    {
        $stmt = $this->pdo->prepare('SELECT * FROM books'); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); 
}
public function getById($id)
{
    $stmt = $this->pdo->prepare('SELECT * FROM books WHERE id = ?');
    $stmt->execute([$id]);
    return $stmt->fetch(PDO::FETCH_ASSOC);
}

public function create($title, $author)
{
    $stmt = $this->pdo->prepare('INSERT INTO books (title, author) VALUES (?, ?)');
    $stmt->execute([$title, $author]);
    return $this->getById($this->pdo->lastInsertId());
}

public function update($id, $title, $author)
{
    $stmt = $this->pdo->prepare('UPDATE books SET title = ?, author = ? WHERE id = ?');
    $stmt->execute([$title, $author, $id]);
    return $this->getById($id);
}

public function delete($id)
{
    $stmt = $this->pdo->prepare('DELETE FROM books WHERE id = ?');
    $stmt->execute([$id]);
    return true;
}
}
?>

This class has methods for getting all books, getting a book by ID, creating a new book, updating a book by ID, and deleting a book by ID.

The BookController.php file should contain the following code:



<?php

namespace App;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class BookController
{
    private $book;

    public function __construct(Book $book)
    {
        $this->book = $book;
    }

    public function getAll(Request $request, Response $response, $args)
    {
        $books = $this->book->getAll();
        return $response->withJson($books);
    }

    public function getById(Request $request, Response $response, $args)
    {
        $id = $args['id'];
        $book = $this->book->getById($id);
        if (!$book) {
            return $response->withStatus(404);
        }
        return $response->withJson($book);
    }

    public function create(Request $request, Response $response, $args)
    {
        $body = $request->getParsedBody();
        $title = $body['title'] ?? null;
        $author = $body['author'] ?? null;
        if (!$title || !$author) {
            return $response->withStatus(400);
        }
        $book = $this->book->create($title, $author);
        return $response->withJson($book)->withStatus(201);
    }

    public function update(Request $request, Response $response, $args)
    {
        $id = $args['id'];
        $body = $request->getParsedBody();
        $title = $body['title'] ?? null;
        $author = $body['author'] ?? null;
        if (!$title || !$author) {
            return $response->withStatus(400);
        }
        $book = $this->book->update($id, $title, $author);
        return $response->withJson($book);
    }

    public function delete(Request $request, Response $response, $args)
    {
        $id = $args['id'];
        $book = $this->book->getById($id);
        if (!$book) {
            return $response->withStatus(404);
        }
        $this->book->delete($id);
        return $response->withStatus(204);
    }
?>

This class is responsible for handling HTTP requests and responses for the books resources. Each method corresponds to a different HTTP verb and handles the appropriate action for that verb.

The index.php file should contain the following code:

<?php

use App\Book;
use App\BookController;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->addErrorMiddleware(true, true, true);

$book = new Book();
$bookController = new BookController($book);

$app->get('/books', [$bookController, 'getAll']);
$app->get('/books/{id}', [$bookController, 'getById']);
$app->post('/books', [$bookController, 'create']);
$app->put('/books/{id}', [$bookController, 'update']);
$app->delete('/books/{id}', [$bookController, 'delete']);

$app->run();
?>

This file sets up the Slim application and defines the routes for the books resource. Each route corresponds to a different HTTP verb and calls the appropriate method in the BookController class.

To test the API, you can use a tool like Postman or cURL to make requests to the API. Here are some example requests:

GET /books

Returns a list of all books.

GET /books/1

Returns the book with ID 1.

POST /books
{
  "title": "The Great Gatsby",
  "author": "F. Scott Fitzgerald"
}

Creates a new book with the title "The Great Gatsby" and author "F. Scott Fitzgerald".

PUT /books/1
{
  "title": "The Great Gatsby",
  "author": "F. Scott Fitzgerald"
}

Updates the book with ID 1 to have the title "The Great Gatsby" and author "F. Scott Fitzgerald".

DELETE /books/1

Deletes the book with ID 1.

If you've made it this far in the tutorial, congratulations! You now have the power to build your own REST API and take over the world (or at least the web). Just don't forget to take breaks and enjoy some snacks along the way - after all, even the most brilliant developers need to refuel with some pizza and caffeine every now and then. Happy coding, and may your API bring joy and laughter to all who use it!

Did you find this article valuable?

Support Shital Mainali by becoming a sponsor. Any amount is appreciated!