Create a Rest API in PHP and Consume it in React Part 1
In this tutorial, we will see how to create a rest API in PHP and consume it in React, it is an events app the user can browse events, register, and log in using his credentials, and once he is logged in he will get an access token that allows him to log out.
MySQL Tables
First, let's create the database I gave it 'php_events' as the name and added the following tables inside:
CREATE TABLE `api_keys` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`api_key` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `categories` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `categories` (`id`, `name`) VALUES
(1, 'Sport'),
(2, 'Movies');
CREATE TABLE `events` (
`id` int(11) NOT NULL,
`title` varchar(255) NOT NULL,
`description` longtext NOT NULL,
`category_id` int(11) NOT NULL,
`tickets_availlable` int(11) NOT NULL,
`event_date` datetime NOT NULL,
`event_address` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `events` (`id`, `title`, `description`, `category_id`, `tickets_availlable`, `event_date`, `event_address`) VALUES
(1, 'Spider man', 'ed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae.', 2, 100, '2023-07-26 13:09:32', '10th street food'),
(2, 'Classico Barca vs Real', 'ed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiamtae.', 1, 200, '2023-07-17 13:09:32', '4th street away');
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `api_keys`
ADD PRIMARY KEY (`id`),
ADD KEY `api_keys_ibfk` (`user_id`);
ALTER TABLE `categories`
ADD PRIMARY KEY (`id`);
ALTER TABLE `events`
ADD PRIMARY KEY (`id`),
ADD KEY `category_id` (`category_id`);
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
ALTER TABLE `api_keys`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
ALTER TABLE `categories`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
ALTER TABLE `events`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
ALTER TABLE `api_keys`
ADD CONSTRAINT `api_keys_ibfk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
ALTER TABLE `events`
ADD CONSTRAINT `events_ibfk` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`);
Connect to the database
The structure of our project will be like this:
- src
-App
-Controllers
-Models
-Database
.htaccess
composer.json
index.php
so inside src, we have the files .htaccess, composer.json, and index.php, we have also the folder App which contains folders (controllers, models, database).
Now inside the folder Database we add a new file Database.php here we connect our app to the MySQL database.
namespace App\Database;
use PDO;
class Database
{
private $servername = 'localhost';
private $username = 'root';
private $password = '';
private $dbname = 'php_events';
public function connect()
{
try {
$db = new PDO("mysql:host=$this->servername;dbname=$this->dbname",
$this->username, $this->password);
$db->exec("set names utf8");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $db;
} catch (PDOException $e) {
echo "Connection failed ". $e->getMessage();
}
}
}
Auto loading Classes
Next, to auto-load classes add the following code inside composer.json and run the command:
composer dump-autoload
{
"autoload": {
"psr-4": {
"App\\":"src/App"
}
}
}
Create EventModel
Inside models, we add a new file 'EventModel' Here we have functions for fetching all events, events by category, and one single event by id.
<?php
namespace App\Models;
use App\Database\Database as DB;
use PDO;
class EventModel
{
private $conn;
public function __construct()
{
$database = new DB;
$this->conn = $database->connect();
}
public function fetchAllEvents()
{
$data = [];
$stmt = $this->conn->prepare("SELECT * FROM events");
$stmt->execute();
$events = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($events as $event) {
$category = $this->fetchEventCategory($event);
array_push($data, array_merge($event, $category));
}
return $data;
}
public function fetchEventCategory($event)
{
$stmt = $this->conn->prepare("SELECT name as category_name FROM categories
WHERE id = :category_id");
$stmt->bindParam(':category_id', $event['category_id'], PDO::PARAM_INT);
$stmt->execute();
$category = $stmt->fetch(PDO::FETCH_ASSOC);
return $category;
}
public function fetchEvent($event_id)
{
$stmt = $this->conn->prepare("SELECT * FROM events
WHERE id = :event_id");
$stmt->bindParam(':event_id', $event_id, PDO::PARAM_INT);
$stmt->execute();
$event = $stmt->fetch(PDO::FETCH_ASSOC);
if(!$event) {
http_response_code(404);
return $data = [
'error' => true,
'message' => 'The event you are looking for does not exist.'
];
}
$category = $this->fetchEventCategory($event);
$data = array_merge($event, $category);
return $data;
}
public function fetchEventByCategory($category_id)
{
$stmt = $this->conn->prepare("SELECT * FROM events
WHERE category_id = :category_id");
$stmt->bindParam(':category_id', $category_id, PDO::PARAM_INT);
$stmt->execute();
$events = $stmt->fetchAll(PDO::FETCH_ASSOC);
if(!$events) {
http_response_code(404);
return $data = [
'error' => true,
'message' => 'No results found.'
];
}
return $events;
}
}
Create EventController
Inside controllers, we add a new file 'EventController' Here we call functions already added in the 'EventModel'.
<?php
namespace App\Controllers;
use App\Models\EventModel as Event;
class EventController
{
private $model;
public function __construct()
{
$this->model = new Event;
}
public function index()
{
$events = $this->model->fetchAllEvents();
echo json_encode([
'events' => $events
]);
}
public function show($event_id)
{
$event = $this->model->fetchEvent($event_id);
echo json_encode([
'event' => $event
]);
}
public function eventsByCategory($category_id)
{
$events = $this->model->fetchEventByCategory($category_id);
echo json_encode([
'events' => $events
]);
}
}