RESTful API CRUD using PHP and MySQL Database Tutorial

Introduction

In this tutorial, you will learn how to create a RESTful API CRUD using PHP Language and MySQL Database. This tutorial aims to provide a reference or guide to the students and for those new to PHP Language about implementing a RESTful API on their projects. Here, snippets are provided and the source code zip file is free to download.

What is REST API?

REST API is also known as RESTful API. REST stands for REpresentational State Transfer. It is a REST architectural style-compliant application programming interface (API or web API) that enables communication with RESTful online services.

REST API is usually implemented in a project that allows the client to manage or retrieve data from the server for their own use. For example, Website 1 wants to dynamically retrieve data from Website 2 and display it on its own website. By creating a REST API on Website 2, Website 1 can create a request to the server of website 2 over HTTP and retrieve the return data.

Creating a Simple RESTful API in PHP

Here, we will create a Simple CRUD REST API using PHP and MySQL as the Database.

Getting Started

Since we will be using PHP Scripts and MySQL Database in this tutorial, kindly download and install a XAMPP or any equivalent software on your local machine to run PHP Scripts and for the local MySQL Database. For those using XAMPP, don't forget to start the Apache and MySQL servers at the XAMPP's Control Panel.

Database

First, we will create a database naming dummy_db. Next, copy the MySQL Schema below and run it into your newly created database SQL Page.

  1. CREATE TABLE `programming_languages` (
  2.     `abbrv` varchar(250) NOT NULL,
  3.     `name` text NOT NULL,
  4.     `short_description` text NOT NULL,
  5.     `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  6.  
  7. CREATE TABLE `token_list` (
  8.     `token` text NOT NULL
  9.      

Executing the MySQL Schema above to your created database will result in creating 2 new tables which are programming_languages and token_list. The token_list is where the valid tokens will be stored and programming_languages is the storage of the sample data that will manage using REST API.

Database Connection

Next, we'll create the database base connection script. In your source code folder, create a new PHP File named db-connect.php and open it with your preferred text editor. Then, write your DB Connection Script on it. The below snippet is the one I am using on my end.

  1. <?php
  2. $host = "localhost";
  3. $username = "root";
  4. $pw = "";
  5. $db_name = "dummy_db";
  6.  
  7. $conn = new mysqli($host, $username, $pw, $db_name);
  8.  
  9. if(!$conn){
  10.     die("Database Connection Failed");
  11. }

Generate Sample Tokens

Next, we'll create a simple script for generating valid tokens. The tokens will be used for validating the request in REST API as a simple security of the data using the said API. Create a new PHP File and save it as generate-tokens.php. Use the following snippet for this file.

  1. <?php
  2. require_once('db-connect.php');
  3.  
  4. /**
  5.     * truncate all tokens
  6.     */
  7.  
  8. $truncate_sql = "TRUNCATE `token_list`";
  9. $truncate_tbl = $conn->query($truncate_sql);
  10. if($truncate_tbl){
  11.     print("Token Table has been truncated successfully.<br>");
  12. }else{
  13.     print("Truncating Table Failed due to some reasons. Error:". $conn->error);
  14. }
  15.  
  16. $tokens = [];
  17.  
  18. for($i = 0; $i < 5; $i++){
  19.     while(true){
  20.         $key = mt_rand(111, mt_getrandmax());
  21.         $token = md5($key);
  22.         if(!in_array($token, $tokens)){
  23.             $tokens[] = addslashes($conn->real_escape_string($token));
  24.             break;
  25.         }
  26.     }
  27. }
  28.  
  29. /**
  30.     * Inserting Tokens to database
  31.     */
  32.  
  33. $insert_sql = "INSERT INTO `token_list` (`token`) VALUES";
  34. $insert_sql .= "('". (implode("'), ('", $tokens)) ."')";
  35. $insert = $conn->query($insert_sql);
  36. if($insert_sql){
  37.     print("Tokens has been generated.<br>");
  38.     echo "<pre>";
  39.     print_r(json_encode($tokens, JSON_PRETTY_PRINT));
  40.     echo "</pre>";
  41. }else{
  42.     print("Inserting Tokens Failed. Error:". $conn->error);
  43. }
  44. $conn->close();

After creating the file, browse the script on your web browser i.e. http://localhost/php-restful-api/generate-tokens.php. Then, on your database, check if the generated tokens are successfully inserted on the `token_list` table.

Creating the PHP CRUD REST API

Next, we will now create the PHP Script that serves as the API on our server. Create a new PHP File and save it as api.php. The below snippet is PHP Script I created using the Object-oriented programming (OOP) approach. It contains all the CRUD processes on the database.

  1. <?php
  2. header("Content-Type:application/json");
  3. require_once('db-connect.php');
  4.  
  5. class API {
  6.     public $db;
  7.     function __construct(){
  8.         global $conn;
  9.         $this->db = $conn;
  10.     }
  11.  
  12.     /**
  13.         * Verify Token
  14.         */
  15.    
  16.     function verify_token($token=""){
  17.         $validity = false;
  18.         if(!empty($token)){
  19.             $check_token = $this->db->query("SELECT id FROM `token_list` where `token` = '{$token}'")->num_rows;
  20.             if($check_token > 0)
  21.             return true;
  22.         }
  23.     }
  24.  
  25.     /**
  26.         * POST Request
  27.         * - insert data to database
  28.         */
  29.  
  30.     function new_language(){
  31.         if(isset($_SERVER['REQUEST_METHOD']) == "POST"){
  32.             $data  = "";
  33.             foreach($_POST as $k => $v){
  34.                 if(!is_numeric($v))
  35.                 $v = addslashes($this->db->real_escape_string($v));
  36.  
  37.                 if(!empty($data)) $data .= ", ";
  38.                 $data .= " `{$k}` = '{$v}'";
  39.             }
  40.  
  41.             $insert_sql = "INSERT INTO `programming_languages` set {$data}";
  42.             // return ['sql' => $insert_sql, 'POST' => $_REQUEST];
  43.             $insert = $this->db->query($insert_sql);
  44.             if($insert){
  45.                 $resp['status'] = 'success';
  46.                 $resp['message'] = 'New Data has been saved successfully.';
  47.                 $id = $this->db->insert_id;
  48.                 $get = $this->db->query("SELECT * FROM `programming_languages` where `id` = '{$id}'")->fetch_assoc();
  49.                 $resp['result'] = $get;
  50.             }else{
  51.                 $resp['status'] = 'failed';
  52.                 $resp['error'] = $this->db->error;
  53.             }
  54.             return $resp;
  55.  
  56.         }else{
  57.             $resp['status'] = 'failed';
  58.             $resp['error'] = "This API Method must contain valid POST Data";
  59.             return $resp;
  60.         }
  61.     }
  62.  
  63.     /**
  64.         * POST Request
  65.         * - List all Table data to database
  66.         */
  67.  
  68.     function get_languages(){
  69.         $sql = "SELECT * FROM `programming_languages`";
  70.         $query = $this->db->query($sql);
  71.         $resp['status'] = 'success';
  72.         $resp['num_rows'] = $query->num_rows;
  73.         $resp['result'] = $query->fetch_all(MYSQLI_ASSOC);
  74.         return $resp;
  75.     }
  76.     /**
  77.         * POST Request
  78.         * - List all Table data to database
  79.         */
  80.  
  81.     function get_language_by_id(){
  82.         extract($_GET);
  83.         if(!isset($id)){
  84.             $resp['status'] = 'failed';
  85.             $resp['error'] = "This API Method requires an ID Parameter";
  86.         }else{
  87.             if(!is_numeric($id)){
  88.                 $resp['status'] = 'failed';
  89.                 $resp['error'] = "ID must be an integer.";
  90.             }else{
  91.                 $sql = "SELECT * FROM `programming_languages` where id = {$id}";
  92.                 $query = $this->db->query($sql);
  93.                 if($query->num_rows > 0){
  94.                     $resp['status'] = 'success';
  95.                     $resp['result'] = $query->fetch_assoc();
  96.                 }else{
  97.                     $resp['status'] = 'failed';
  98.                     $resp['error'] = "Invalid given ID.";
  99.                 }
  100.             }
  101.            
  102.         }
  103.         return $resp;
  104.  
  105.     }
  106.  
  107.     /**
  108.         * POST Request
  109.         * - Update data from database
  110.         */
  111.  
  112.     function update_language(){
  113.         if(isset($_SERVER['REQUEST_METHOD']) == "POST"){
  114.             $id = $_POST['id'];
  115.             if(!isset($id)){
  116.                 $resp['status'] = 'failed';
  117.                 $resp['error'] = "This API Method requires an ID Parameter";
  118.             }else{
  119.  
  120.                 $data  = "";
  121.                 foreach($_POST as $k => $v){
  122.                     if($k == 'id')
  123.                     continue;
  124.                     if(!is_numeric($v))
  125.                     $v = addslashes($this->db->real_escape_string($v));
  126.  
  127.                     if(!empty($data)) $data .= ", ";
  128.                     $data .= " `{$k}` = '{$v}'";
  129.                 }
  130.  
  131.                 $update_sql = "UPDATE `programming_languages` set {$data} where id = '{$id}'";
  132.                 // return ['sql' => $update_sql, 'POST' => $_REQUEST];
  133.                 $update = $this->db->query($update_sql);
  134.                 if($update){
  135.                     $resp['status'] = 'success';
  136.                     $resp['message'] = 'Data has been saved successfully.';
  137.                     $get = $this->db->query("SELECT * FROM `programming_languages` where `id` = '{$id}'")->fetch_assoc();
  138.                     $resp['result'] = $get;
  139.                 }else{
  140.                     $resp['status'] = 'failed';
  141.                     $resp['error'] = $this->db->error;
  142.                 }
  143.             }
  144.         }else{
  145.             $resp['status'] = 'failed';
  146.             $resp['error'] = "This API Method must contain valid POST Data";
  147.         }
  148.         return $resp;
  149.     }
  150.  
  151.     /**
  152.         * POST Request
  153.         * - Delete data from database
  154.         */
  155.  
  156.     function delete_language(){
  157.         if($_SERVER['REQUEST_METHOD'] == "DELETE"){
  158.         if(!isset($_GET['id'])){
  159.             $resp['status'] = "error";
  160.             $resp['error'] = "The request must contain an ID Paramater.";
  161.         }else{
  162.             $id = $_GET['id'];
  163.             if(!is_numeric($id)){
  164.                 $resp['status'] = "error";
  165.                 $resp['error'] = "The ID Parameter must be an integer.";
  166.             }else{
  167.                 $delete = $this->db->query("DELETE FROM `programming_languages` where `id` = {$id}");
  168.                 if($delete){
  169.                     $resp['status'] = 'success';
  170.                     $resp['message'] = "Programming Language with the #{$id} ID has been deleted successfully";
  171.                 }else{
  172.                     $resp['status'] = "error";
  173.                     $resp['error'] = "Deleting Data from Database Failed! Error:". $this->db->error;
  174.                 }
  175.             }
  176.         }
  177.         }else{
  178.         $resp['status'] = "error";
  179.         $resp['error'] = "The request method is invalid.";
  180.         }
  181.         return $resp;
  182.     }
  183.    
  184.     function __destruct(){
  185.         $this->db->close();
  186.     }
  187. }
  188. $api = new API();
  189. $action = isset($_GET['action']) ? $_GET['action'] : '';
  190.  
  191. /**
  192.     * Get headers
  193.     */
  194. $headers = null;
  195. if (isset($_SERVER['Authorization'])) {
  196.     $headers = trim($_SERVER["Authorization"]);
  197. }
  198. else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI
  199.     $headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
  200. } elseif (function_exists('apache_request_headers')) {
  201.     $requestHeaders = apache_request_headers();
  202.     // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
  203.     $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
  204.     //print_r($requestHeaders);
  205.     if (isset($requestHeaders['Authorization'])) {
  206.         $headers = trim($requestHeaders['Authorization']);
  207.     }
  208. }
  209.  
  210. /**
  211.     * Check if token has provided
  212.     */
  213. $api_key = null;
  214. if(preg_match('/Bearer/i', $headers)){
  215.     $bearer_count = preg_match_all('/Bearer\s(.*)/i',$headers, $bearer_matches);
  216.     if(isset($bearer_matches[1][0]))
  217.     $api_key = trim($bearer_matches[1][0]);
  218. }
  219. if(!is_null($api_key) && !empty($api_key)){
  220.     $verify_api = $api->verify_token($api_key);
  221.     if(!$verify_api){
  222.         echo json_encode([
  223.             'status' => 'failed',
  224.             'error' => "API token is Invalid."
  225.         ]);
  226.         exit;
  227.     }
  228. }else{
  229.     echo json_encode([
  230.         'status' => 'failed',
  231.         'error' => "API Token is Required."
  232.     ]);
  233.     exit;
  234. }
  235. if(method_exists($api, $action)){
  236.     $exec = $api->$action();
  237.     echo json_encode($exec);
  238. }else{
  239.     echo json_encode([
  240.         'status' => 'failed',
  241.         'error' => "API [{$action}] Method does not exists."
  242.     ]);
  243. }
  244. ?>

Example RESTful API Execution using CURL

Here is the sample syntax for executing the CRUD Operation of the API.

Insert New Data (new_language())

In this operation, the client must execute their request using the POST method. The request must contain abbvr, name, and short_description POST data.

  1.     curl -X POST "http://localhost/php-restful-api/api.php?action=new_language" \
  2.     -H "Authorization: Bearer 568asd548as" \
  3.     -H "Accept: application/json"
  4.     --data "abbrv=PHP&name=Hypertext Preprocessor&short_description=Sample Description Only."

Result

RESTful API - INSERT DATA

Update Existing Data (update_language())

In this operation, the client must execute their request using the POST method. The request must contain id, abbvr, name, and short_description POST data.

  1.     curl -X POST "http://localhost/php-restful-api/api.php?action=new_language" \
  2.     -H "Authorization: Bearer 568asd548as" \
  3.     -H "Accept: application/json"
  4.     --data "id=4abbrv=VB.NET&name=Visual Basic .NET&short_description=VB.NET - updated."

Result

RESTful API - Update Data

Get All Data (get_languages())

In this operation, client must execute their request using the GET method.

  1.     curl -X POST "http://localhost/php-restful-api/api.php?action=get_languages" \
  2.     -H "Authorization: Bearer 568asd548as" \
  3.     -H "Accept: application/json"

Result

RESTful API - Update Data

Get Single Data using ID (get_language_by_id())

In this operation, the client must execute their request using the GET method. The request must contain an ID parameter.

  1.     curl -X POST "http://localhost/php-restful-api/api.php?action=get_language_by_id&id=1" \
  2.     -H "Authorization: Bearer 568asd548as" \
  3.     -H "Accept: application/json"

Result

RESTful API - Update Data

Delete Data (delete_language())

In this operation, the client must execute their request using the GET method. The request must contain an ID parameter.

  1.     curl -X POST "http://localhost/php-restful-api/api.php?action=delete_language&id=1" \
  2.     -H "Authorization: Bearer 568asd548as" \
  3.     -H "Accept: application/json"

Result

RESTful API - Update Data

DEMO VIDEO

That's it! Now you can test the PHP CRUD RESTful API we created on your end and see if it works properly. You also test it using some online REST API Tester sites. I have also provided the complete source code file I created for this tutorial. You can download it for free by clicking the Download Button below this article.

That's the end of this tutorial! I hope this PHP CRUD RESTful API using PHP and MySQL Tutorial will help you with what you are looking for and that you'll find this useful for your current and future PHP Projects.

Happy Coding :)

Add new comment