Create a REST API in PHP
REST APIs are used to exchange data using simple HTTP methods, allowing different applications to communicate with each other over the internet.

REST APIs are widely used for stateless communication between client and server or different applications over the internet, most commonly using HTTP methods. In this post, we are going to create a REST API in PHP and demonstrate how it is used to exchange data over the internet. We will also implement an authorization token to authorize all requests.
The files we are going to create for this post are:
- constants.php: Contains the constants for the database connection.
- db.php: Serves as a database abstraction layer containing reusable database functions.
- api.php: Contains the code for REST API requests and serves as an API endpoint.
What is a REST API?
REST stands for Representational State Transfer, which means how the current state or data of a resource is represented. A REST resource can be anything like an employee, a product, or a book, and the representation of its current state can be JSON or XML. In REST, each resource has a different URL. REST is used for stateless communication, which means each request is independent and must contain all required data for the server to understand the request. This stateless communication takes place using HTTP methods like GET, POST, PUT, and DELETE.
Whereas API stands for Application Programming Interface, which is an interface that allows different platforms to communicate. The code snippets provided in this post will help you to implement a PHP REST API interface in your application with a working demo and source code available for download.
HTTP Methods Used in REST
As explained, REST uses HTTP methods for communication and state transfer. The following are the most commonly used HTTP methods in REST.
- GET - To get a single or multiple records
- POST - To add a new record
- PUT - To update a record
- DELETE - To delete a single record
URL Structure Used in REST
The URLs in REST can be of any structure, but as a standard, the following structure is used for different HTTP methods.
- GET /employees: Fetch all employee records.
- GET /employees/1: Fetch single employee record with id of 1.
- POST /employees: Add a new employee record to the database.
- PUT /employees/1: Update a single employee record with the id 1.
- DELETE /employees/1: Delete a single employee record with the id 1.
Now that we have an understanding of what a REST API structure is, let us start with a practical implementation and create a PHP REST API.
How to Build a REST API in PHP (With CRUD and Authorization Token)
Building a PHP REST API with an authorization token and basic CRUD can be easily achieved in a few steps as follows:
- Create a
constants.phpfile to hold database constants. - Create a
db.phpwith database helper functions. - Create an
api.phpfile to consume API requests and return responses. Handle authorization checks in this file. - Create an
.htaccessfile to rewrite URLs for API endpoints. - Finally, test the REST API implementation.
Step 1: Add Database & REST API Constants
Add constants for database connection and REST authorization token.
constants.php
<?php
define('DB_HOST', 'DATABASE_HOSTNAME'); // Your database host
define('DB_NAME', 'DATABASE_NAME'); // Your database name
define('DB_USER', 'DATABASE_USERNAME'); // Username for database
define('DB_PASSWORD', 'DATABASE_PASSWORD'); // Password for database
define('REST_AUTH_TOKEN', 'REST_AUTH_TOKEN'); // Authorization token
Step 2: Create a Database Helper Functions
Create a file that will contain database functions to easily perform database SELECT, INSERT, UPDATE, and DELETE queries with reusable functions for our API endpoint file.
db.php
<?php
// Disable error reporting
error_reporting(0);
include 'constants.php';
global $db_connection;
// Open database connection
$db_connection = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) or die(mysqli_connect_error());
/**
* Function to fetch records from table
* @param string $sql
* @param string $types
* @param array $params
* @return string|array
*/
function db_get(string $sql, string $types = '', array $params = []): array|string
{
global $db_connection;
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
if (!empty($params)) {
mysqli_stmt_bind_param($stmt, $types, ...$params);
}
mysqli_stmt_execute($stmt);
if ($result = mysqli_stmt_get_result($stmt)) {
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
mysqli_stmt_close($stmt);
return mysqli_error($db_connection);
}
/**
* Function to add record to database table,
* @param string $table
* @param array $data
* @return string|int
*/
function db_insert(string $table, array $data): string|int
{
global $db_connection;
$columns = array_keys($data);
$sql = "INSERT INTO $table (" . implode(',', $columns) . ") VALUES (" . implode(',', array_fill(0, count($data), '?')) . ")";
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
mysqli_stmt_bind_param($stmt, str_repeat('s', count($data)), ...array_values($data));
if (mysqli_stmt_execute($stmt)) {
return mysqli_insert_id($db_connection);
}
mysqli_stmt_close($stmt);
return mysqli_error($db_connection);
}
/**
* Function to update record in database table,
* @param string $table
* @param array $data
* @param string $where
* @param string $where_types
* @param array $where_params
* @return string|bool
*/
function db_update(string $table, array $data, string $where, string $where_types, array $where_params): string|bool
{
global $db_connection;
$bind = [];
foreach ($data as $key => $value) {
$bind[] = "$key = ?";
}
$sql = "UPDATE $table SET " . implode(', ', $bind) . " WHERE $where";
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
mysqli_stmt_bind_param($stmt, str_repeat('s', count($data)) . $where_types, ...array_merge(array_values($data), $where_params));
$result = mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
return $result;
}
/**
* Function to delete record from database table,
* @param string $table
* @param string $where
* @param string $types
* @param array $params
* @return string|bool
*/
function db_delete(string $table, string $where, string $types, array $params): string|bool
{
global $db_connection;
$sql = "DELETE FROM $table WHERE $where";
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
mysqli_stmt_bind_param($stmt, $types, ...$params);
$result = mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
return $result;
}
Step 3: Create a REST API in PHP
Our api.php is basically our REST API endpoint and handles the client-server REST communication for requests. We return different responses based on the request method, and we also handle the API authorization with a token. The following are the steps to create a simple REST API in PHP:
- Set HTTP headers to
application/jsonand tell the server to send a JSON response. - Set the access control header to allow only
GET,POST,PUT, andDELETEmethods. This tells the client API accepts only these HTTP methods. - Set access control to allow only
Content-Type,Authorization, andX-Requested-Withheaders. - Set cache headers to not cache and store the API response.
- Check if the authorization header in the request has the authorization token. If it is missing, set the HTTP response and return a JSON response with an appropriate error message.
- Check if request headers contain the content type, either
application/jsonorapplication/x-www-form-urlencoded. If the content type is not one of these, return an error response. - Prepare an array of request data as the
$inputvariable, based on the content type the client sent in the header. - Handle each request for the request method provided using a switch statement. The request method can be one of these (GET, POST, PUT, DELETE) methods. Perform action based on the request method in each switch case and set the response code.
- Finally, at the end, set the HTTP response code using the
http_response_code()method and return the response as JSON.
api.php
<?php
include 'db.php';
// SET application header, allowed methods & headers
header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Cache-Control: no-cache,no-store,must-revalidate');
header('Pragma: no-cache');
// Get all request headers & and lower case header keys to handle case sensitivity
$request_headers = array_change_key_case(getallheaders(), CASE_LOWER);
// Set initial response code to current code
$response_code = http_response_code();
// Check if request contains authorization token
if (!isset($request_headers['authorization']) || ($request_headers['authorization'] !== REST_AUTH_TOKEN)) {
$res = [
'success' => 0,
'message' => 'Unauthorized request'
];
http_response_code(401);
die(json_encode($res, JSON_PRETTY_PRINT));
}
// Check if request contains proper content type
if (!isset($request_headers['content-type'])
|| (($request_headers['content-type'] !== 'application/x-www-form-urlencoded')
&& ($request_headers['content-type'] !== 'application/json'))) {
$res = [
'success' => 0,
'message' => 'Set content-type to application/x-www-form-urlencoded or application/json'
];
http_response_code(400);
die(json_encode($res, JSON_PRETTY_PRINT));
}
// Get the method used to call API
$request_method = $_SERVER['REQUEST_METHOD'];
// Raw input received in request
$input_raw = file_get_contents('php://input');
// Prepare input for both json/x-www-form-urlencoded
$input_json = json_decode($input_raw, true); // Decode input to json
parse_str($input_raw, $input_arr); // Parse x-www-form-urlencoded to arrays
$input = [];
if (is_array($input_json)) {
// If input was json set this input to be used in script
$input = $input_json;
} elseif (is_array($input_arr)) {
// If input was x-www-form-urlencoded set this input to be used in script
$input = $input_arr;
}
$input = array_map('filter_var', $input);
switch ($request_method) {
case 'GET':
// If employee id was passed , Fetch record against that id only
if (isset($_GET['id'])) {
$employees = db_get('SELECT id,full_name,gender,email,designation FROM employees WHERE id = ?',
'i',
[intval($_GET['id'])]);
} else {
$employees = db_get("SELECT id,full_name,gender,email,designation FROM employees");
}
$total = count($employees);
// Set json response after getting employee record(s)
$res = [
'success' => 1,
'data' => $employees,
'total' => $total
];
$response_code = 200;
break;
case 'POST':
// Set json response if full name & email was empty
if (empty($input['full_name']) && empty($input['email'])) {
$res = [
'success' => 0,
'message' => 'Employee name and email cannot be empty'
];
$response_code = 400;
break;
}
$data = [];
$data['full_name'] = $input['full_name'];
$data['email'] = $input['email'];
$data['gender'] = $input['gender'];
$data['designation'] = $input['designation'];
db_insert('employees', $data);
// Return json response after adding employee
$res = [
'success' => 1,
'message' => 'Employee has been added'
];
$response_code = 200;
break;
case 'PUT':
// Set json response if no employee id was provided to update against
if (!isset($_GET['id'])) {
$res = [
'success' => 0,
'message' => 'Missing parameter id'
];
$response_code = 400;
break;
}
// Set json response if full name or email was provided empty
if (empty($input['full_name']) || empty($input['email'])) {
$res = [
'success' => 0,
'message' => 'Employee name and email cannot be empty'
];
$response_code = 400;
break;
}
$data['full_name'] = $input['full_name'];
$data['email'] = $input['email'];
$data['gender'] = $input['gender'];
$data['designation'] = $input['designation'];
db_update('employees', $data, 'id = ?', 'i', [intval($_GET['id'])]);
// Set json response after updating employee
$res = [
'success' => 1,
'message' => 'Employee has been updated'
];
$response_code = 200;
break;
case 'DELETE':
if (!isset($_GET['id'])) {
$res = [
'success' => 0,
'message' => 'Missing parameter id'
];
$response_code = 400;
break;
}
db_delete('employees', 'id = ?', 'i', [intval($_GET['id'])]);
// Set json response after deleting employee
$res = [
'success' => 1,
'message' => 'Employee has been deleted'
];
$response_code = 200;
break;
default:
// If requested method was other than GET,POST,PUT,DELETE, return an error message
$res = [
'success' => 0,
'message' => 'Invalid request'
];
$response_code = 400;
break;
}
// Set response status code
http_response_code($response_code);
// Return final json response
echo json_encode($res);
Step 4: Rewrite URLs with .htaccess
Now that everything is ready to test our API, there is one last step to rewrite URLs with .htaccess for a pretty URL structure.
DirectoryIndex api.phpThis will change our URL to
RewriteEngine On
## Replace Rewritebase to directory where you place downloaded files
RewriteBase /www/create-rest-api-in-php/
RewriteRule ^api/(\d+)$ api.php?id=$1 [L,NC,QSA]
RewriteRule ^api/?$ api.php [L,NC,QSA]
http://yourdomain.com/apifolder/api. Now open the postman application and test all methods one by one. Responses should match as in the screenshots below:- GET / All Records
- GET / Single Record

- POST / Add New Record