Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 21, 2020 09:09 pm GMT

Build a Simple REST API in PHP

REpresentational State Transfer (REST) is a software architectural style that defines a set of constraints to be used for creating Web Services. REST APIs are one of the pillars of modern web development. Most web applications these days are developed as single-page applications on the frontend, connected to backend APIs written in different languages. There are various PHP frameworks which could help you build a REST API in minutes. But, let us learn how to build a simple REST API in core PHP.

This is the first part of the Learn PHP series, where you'll learn how to build a REST API in PHP using core PHP.

Upcoming two:

Prerequisites

PHP REST API Skeleton

Create a /src directory, and a composer.json file in the top directory with one dependency: the DotEnv library, which allows storing secured pieces of information in .env file.

composer.json

{  "require": {    "vlucas/phpdotenv": "^5.2"  },  "autoload": {    "psr-4": {      "Src\\": "src/"    }  }}
Enter fullscreen mode Exit fullscreen mode

A PSR-4 autoloader will automatically look for PHP classes in the /src directory.

Install dependencies now:

composer install
Enter fullscreen mode Exit fullscreen mode

It will create a /vendor directory, and the DotEnv dependency will be installed (autoloader will load classes from /src with no include() calls).

Create a .gitignore file for your project with two lines in it, so the /vendor directory and local .env file will be ignored:

.gitignore

vendor/.env
Enter fullscreen mode Exit fullscreen mode

Next, create a .env.example file for Secret variables:

.env.example

DB_HOST=localhostDB_PORT=3306DB_DATABASE=DB_USERNAME=DB_PASSWORD=
Enter fullscreen mode Exit fullscreen mode

and a .env file where you'll fill in your actual details later (it will be ignored by Git so it wont end up in your repository).

Create a start.php file which loads the environment variables.

start.php

<?phprequire 'vendor/autoload.php';use Dotenv\Dotenv;use Src\Database;$dotenv = new DotEnv(__DIR__);$dotenv->load();// test code:// it will output: localhost// when you run $ php start.phpecho getenv('DB_HOST');
Enter fullscreen mode Exit fullscreen mode

Configure the Database for your PHP REST API

We will use MySQL to power our simple API.
Create a new database and user for your app:

mysql -u root -pCREATE DATABASE blog CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;CREATE USER 'rest_api_user'@'localhost' identified by 'rest_api_password';GRANT ALL on blog.* to 'rest_api_user'@'localhost';quit
Enter fullscreen mode Exit fullscreen mode

The REST API will contain posts for our Blog Application, with the following fields: id, title, body, author, author_picture, created_at. It allows users to post their blog on our Blog application.

Create the database table in MySQL.

mysql -u rest_api_user -p;// Enter your passworduse blog;CREATE TABLE `post` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `title` varchar(255) NOT NULL,  `body` text NOT NULL,  `author` varchar(255),  `author_picture` varchar(255),  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,  PRIMARY KEY (`id`));
Enter fullscreen mode Exit fullscreen mode

Add the database connection variables to your .env file:

.env

DB_HOST=localhostDB_PORT=3306DB_DATABASE=blogDB_USERNAME=rest_api_userDB_PASSWORD=rest_api_password
Enter fullscreen mode Exit fullscreen mode

Create a class to hold the database connections and add the initialization of the connection to the start.php file.

src/Database.php

<?phpnamespace Src;class Database {  private $dbConnection = null;  public function __construct()  {    $host = getenv('DB_HOST');    $port = getenv('DB_PORT');    $db   = getenv('DB_DATABASE');    $user = getenv('DB_USERNAME');    $pass = getenv('DB_PASSWORD');    try {      $this->dbConnection = new \PDO(          "mysql:host=$host;port=$port;dbname=$db",          $user,          $pass      );    } catch (\PDOException $e) {      exit($e->getMessage());    }  }  public function connet()  {    return $this->dbConnection;  }}
Enter fullscreen mode Exit fullscreen mode

start.php

<?phprequire 'vendor/autoload.php';use Dotenv\Dotenv;use Src\Database;$dotenv = new DotEnv(__DIR__);$dotenv->load();$dbConnection = (new Database())->connet();
Enter fullscreen mode Exit fullscreen mode

Add a Class for the Post Table and Implement PHP REST API

There are many ways to interact with the database in an object-oriented context, but, let us go with a simple method where you will implement methods to return all posts, return a specific post and add/update/delete a post.

Also, the API endpoints which will be handled by our frontend api/index.php.

REST API with the following endpoints:

Your APIs

APICRUDDescription
GET /postsREADGet all the Posts from post table
GET /post/{id}READGet a single Post from post table
POST /postCREATECreate a Post and insert into post table
PUT /post/{id}UPDATEUpdate the Post in post table
DELETE /post/{id}DELETEDelete a Post from post table

api/index.php

<?phprequire "../start.php";use Src\Post;header("Access-Control-Allow-Origin: *");header("Content-Type: application/json; charset=UTF-8");header("Access-Control-Allow-Methods: OPTIONS,GET,POST,PUT,DELETE");header("Access-Control-Max-Age: 3600");header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);$uri = explode( '/', $uri );// all of our endpoints start with /post or /posts// everything else results in a 404 Not Foundif ($uri[1] !== 'post') {    if($uri[1] !== 'posts'){        header("HTTP/1.1 404 Not Found");        exit();    }}if ($uri[1] == 'posts' and isset($uri[2])) {    header("HTTP/1.1 404 Not Found");    exit();}// the post id is, of course, optional and must be a number:$postId = null;if (isset($uri[2])) {    $postId = (int) $uri[2];}$requestMethod = $_SERVER["REQUEST_METHOD"];// pass the request method and post ID to the Post and process the HTTP request:$controller = new Post($dbConnection, $requestMethod, $postId);$controller->processRequest();
Enter fullscreen mode Exit fullscreen mode

src/Post.php

<?phpnamespace Src;class Post {  private $db;  private $requestMethod;  private $postId;  public function __construct($db, $requestMethod, $postId)  {    $this->db = $db;    $this->requestMethod = $requestMethod;    $this->postId = $postId;  }  public function processRequest()  {    switch ($this->requestMethod) {      case 'GET':        if ($this->postId) {          $response = $this->getPost($this->postId);        } else {          $response = $this->getAllPosts();        };        break;      case 'POST':        $response = $this->createPost();        break;      case 'PUT':        $response = $this->updatePost($this->postId);        break;      case 'DELETE':        $response = $this->deletePost($this->postId);        break;      default:        $response = $this->notFoundResponse();        break;    }    header($response['status_code_header']);    if ($response['body']) {        echo $response['body'];    }  }  private function getAllPosts()  {    $query = "      SELECT          id, title, body, author, author_picture, created_at      FROM          posts;    ";    try {      $statement = $this->db->query($query);      $result = $statement->fetchAll(\PDO::FETCH_ASSOC);    } catch (\PDOException $e) {      exit($e->getMessage());    }    $response['status_code_header'] = 'HTTP/1.1 200 OK';    $response['body'] = json_encode($result);    return $response;  }  private function getPost($id)  {    $result = $this->find($id);    if (! $result) {        return $this->notFoundResponse();    }    $response['status_code_header'] = 'HTTP/1.1 200 OK';    $response['body'] = json_encode($result);    return $response;  }  private function createPost()  {    $input = (array) json_decode(file_get_contents('php://input'), TRUE);    if (! $this->validatePost($input)) {      return $this->unprocessableEntityResponse();    }    $query = "      INSERT INTO posts          (title, body, author, author_picture)      VALUES          (:title, :body, :author, :author_picture);    ";    try {      $statement = $this->db->prepare($query);      $statement->execute(array(        'title' => $input['title'],        'body'  => $input['body'],        'author' => $input['author'],        'author_picture' => 'https://secure.gravatar.com/avatar/'.md5(strtolower($input['author'])).'.png?s=200',      ));      $statement->rowCount();    } catch (\PDOException $e) {      exit($e->getMessage());    }    $response['status_code_header'] = 'HTTP/1.1 201 Created';    $response['body'] = json_encode(array('message' => 'Post Created'));    return $response;  }  private function updatePost($id)  {    $result = $this->find($id);    if (! $result) {      return $this->notFoundResponse();    }    $input = (array) json_decode(file_get_contents('php://input'), TRUE);    if (! $this->validatePost($input)) {      return $this->unprocessableEntityResponse();    }    $statement = "      UPDATE posts      SET        title = :title,        body  = :body,        author = :author,        author_picture = :author_picture      WHERE id = :id;    ";    try {      $statement = $this->db->prepare($statement);      $statement->execute(array(        'id' => (int) $id,        'title' => $input['title'],        'body'  => $input['body'],        'author' => $input['author'],        'author_picture' => 'https://secure.gravatar.com/avatar/'.md5($input['author']).'.png?s=200',      ));      $statement->rowCount();    } catch (\PDOException $e) {      exit($e->getMessage());    }    $response['status_code_header'] = 'HTTP/1.1 200 OK';    $response['body'] = json_encode(array('message' => 'Post Updated!'));    return $response;  }  private function deletePost($id)  {    $result = $this->find($id);    if (! $result) {      return $this->notFoundResponse();    }    $query = "      DELETE FROM posts      WHERE id = :id;    ";    try {      $statement = $this->db->prepare($query);      $statement->execute(array('id' => $id));      $statement->rowCount();    } catch (\PDOException $e) {      exit($e->getMessage());    }    $response['status_code_header'] = 'HTTP/1.1 200 OK';    $response['body'] = json_encode(array('message' => 'Post Deleted!'));    return $response;  }  public function find($id)  {    $query = "      SELECT          id, title, body, author, author_picture, created_at      FROM          posts      WHERE id = :id;    ";    try {      $statement = $this->db->prepare($query);      $statement->execute(array('id' => $id));      $result = $statement->fetch(\PDO::FETCH_ASSOC);      return $result;    } catch (\PDOException $e) {      exit($e->getMessage());    }  }  private function validatePost($input)  {    if (! isset($input['title'])) {      return false;    }    if (! isset($input['body'])) {      return false;    }    return true;  }  private function unprocessableEntityResponse()  {    $response['status_code_header'] = 'HTTP/1.1 422 Unprocessable Entity';    $response['body'] = json_encode([      'error' => 'Invalid input'    ]);    return $response;  }  private function notFoundResponse()  {    $response['status_code_header'] = 'HTTP/1.1 404 Not Found';    $response['body'] = null;    return $response;  }}
Enter fullscreen mode Exit fullscreen mode

Let's start the PHP Server and test your APIs with a tool like Postman.

php -S localhost:8008 -t api
Enter fullscreen mode Exit fullscreen mode

Done

Congratulations!! You have successfully built a REST API.

GitHub: https://github.com/shahbaz17/php-rest-api

What's Next

Now, as you have built this application, you may be aware that these endpoints are not protected, and anyone on the internet could take advantage and update/delete/insert data. So, Let's secure this API with authentication and authorization.

In my next article, I will cover how you can take advantage of Magic's Passwordless feature and secure your API with just a few lines of changes to these codes.

Secure your PHP Rest API with Magic.


Original Link: https://dev.to/shahbaz17/build-a-simple-rest-api-in-php-2edl

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To