How To Build A Simple REST API in PHP
How To Build A Simple REST API in PHP
web services. In fact, most web applications these days access and expose data via REST APIs.
With the popularity of front-end frameworks that can consume REST APIs effortlessly, it’s
always going to be a plus for you if your web application exposes REST APIs.
In this article, we’ll build a simple demo application, which allows you to fetch a list of users
from the MySQL database via a REST endpoint.
1 ├── Controller
2 │ └── Api
3 │ ├── BaseController.php
4 │ └── UserController.php
5 ├── inc
6 │ ├── bootstrap.php
7 │ └── config.php
8 ├── index.php
9 └── Model
10 ├── Database.php
11 └── UserModel.php
So that’s the basic setup that we are going to implement in the rest of the post.
Create a Database and Model Classes
In this section, we’ll create a database and the users table. We’ll also create the necessary
model classes that will be used to fetch users from a database.
You could also use a tool like phpMyAdmin if you prefer working with your databases that
way.
Once the rest_api_demo database is created, go ahead and create the users table by
running the following statements.
1 $use rest_api_demo;
That should create the users table in the rest_api_demo database. You will also want to
populate this table with a few dummy records for testing purposes. Insert a few records, and
you’re good to go!
1 <?php
2 class Database
3 {
5
6 public function __construct()
7 {
8 try {
10
11 if ( mysqli_connect_errno()) {
13 }
16 }
17 }
18
20 {
21 try {
23 $result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
24 $stmt->close();
25
26 return $result;
27 } catch(Exception $e) {
29 }
30 return false;
31 }
32
34 {
35 try {
37
40 }
41
42 if( $params ) {
43 $stmt->bind_param($params[0], $params[1]);
44 }
45
46 $stmt->execute();
47
48 return $stmt;
49 } catch(Exception $e) {
51 }
52 }
53 }
This is a database access layer class, which allows us to set up a connection to the MySQL
database. Apart from the connection setup, it contains generic methods
like select and executeStatement that allow us to select records from a database. We won’t
use the Database class directly; instead, we will create corresponding model classes that
extend the Database class in order to access the underlying MySQL database.
Next, let’s create the Model/UserModel.php class with the following contents.
1 <?php
5 {
7 {
8 return $this->select("SELECT * FROM users ORDER BY user_id ASC LIMIT ?", ["i", $li
9 }
10 }
It’s important to note that the UserModel class extends the Database class.
Apart from that, it contains the getUsers method, which allows us to select users from the
MySQL database. It’s mandatory to pass the $limit parameter, which makes sure that it won’t
select all records at once.
Of course, you could define more methods in the UserModel class as per your requirements.
We’ll keep things simple in the context of this tutorial.
So now we have our database and model classes set up. In the next section, we’ll see how to
create controllers and the remaining files in our demo application.
Create Application Layer Components
In this section, we’ll create the remaining files that are required for our demo application to
work.
1 <?php
2 define("DB_HOST", "localhost");
3 define("DB_USERNAME", "demo");
4 define("DB_PASSWORD", "demo");
5 define("DB_DATABASE_NAME", "rest_api_demo");
Make sure to update all the values with the actual ones that you’re using in your installation.
Next, go ahead and create the inc/bootstrap.php file with the following contents.
1 <?php
12 ?>
Firstly, we’ve initialized the PROJECT_ROOT_PATH constant with the directory root of our
application. In this way, we could use the PROJECT_ROOT_PATH constant to prepare absolute
paths in our application. Next, we’ve included the config.php file, which holds the database
connection information. Finally, we've included controller and model files.
1 <?php
2 class BaseController
3 {
4 /**
6 */
8 {
10 }
11
12 /**
14 *
15 * @return array
16 */
18 {
21
22 return $uri;
23 }
24
25 /**
27 *
28 * @return array
29 */
31 {
32 return parse_str($_SERVER['QUERY_STRING'], $query);
33 }
34
35 /**
37 *
40 */
42 {
43 header_remove('Set-Cookie');
44
47 header($httpHeader);
48 }
49 }
50
51 echo $data;
52 exit;
53 }
54 }
The __call method is a magic method, and it’s called when you try to call a method that
doesn't exist. We’re using this opportunity to throw the HTTP/1.1 404 Not Found error when
someone tries to call a method which we haven’t implemented. If this sounds confusing to
you, don't worry—it will make more sense when we test our application in the next section.
Next, there’s the getUriSegments method, which returns an array of URI segments. It’s useful
when we try to validate the REST endpoint called by the user. Following that, there’s
the getQueryStringParams method, which returns an array of query string variables that are
passed along with the incoming request.
Finally, there’s the sendOutput method, which is used to send the API response. We’ll call this
method when we want to send the API response to the user.
3 {
4 /**
6 */
8 {
9 $strErrorDesc = '';
10 $requestMethod = $_SERVER["REQUEST_METHOD"];
11 $arrQueryStringParams = $this->getQueryStringParams();
12
13 if (strtoupper($requestMethod) == 'GET') {
14 try {
16
17 $intLimit = 10;
19 $intLimit = $arrQueryStringParams['limit'];
20 }
21
22 $arrUsers = $userModel->getUsers($intLimit);
23 $responseData = json_encode($arrUsers);
27 }
28 } else {
31 }
32
33 // send output
34 if (!$strErrorDesc) {
35 $this->sendOutput(
36 $responseData,
38 );
39 } else {
40 $this->sendOutput(json_encode(array('error' => $strErrorDesc)),
42 );
43 }
44 }
45 }
It’s important to note that the UserController class extends the BaseController class.
Ideally, this class would contain the action methods that are associated with the REST
endpoints that are defined for the user entity. In our case, for example, the /user/list REST
endpoint corresponds to the listAction method. In this way, you can also define other
methods for other REST endpoints.
The listAction method is used to get a list of users from the MySQL database. It contains
the whole logic of the /user/list REST endpoint.
Lastly, we’ve used the sendOutput method to send the JSON response to the user. It’s
important to note that the response content-type header value is set
to application/json since we’re sending the JSON response.
Similarly, you could define other methods for other endpoints as well.
1 <?php
9 exit();
10 }
11
13
16 $objFeedController->{$strMethodName}();
17 ?>
Firstly, we’ve used parse_url and explode functions to initialize URI segments into
the $uri array variable. Next, we’re validating the URI segments. Finally, we’ve initialized
the UserController controller and called the corresponding action method.
With that, we’ve created all the necessary files in our demo REST application. In the next
section, we’ll see how to call it from the end-user perspective.
1 // https://localhost/index.php/{MODULE_NAME}/{METHOD_NAME}?limit={LIMIT_VALUE}
2 http://localhost/index.php/user/list?limit=20
If you recall the index.php file, we checked if the $uri[2] variable is set to user . Also,
the $uri[3] variable value would act as a method name. In the above case,
the $uri[3] variable is set to list . Thus, it would end up calling the listAction method of
the UserController class.
1 [
2 {
3 "user_id":1,
4 "username":"Bob",
5 "user_email":"bob@gmail.com",
6 "user_status":0
7 },
8 {
9 "user_id":2,
10 "username":"John",
11 "user_email":"john@gmail.com",
12 "user_status":1
13 },
14 {
15 "user_id":3,
16 "username":"Mark",
17 "user_email":"mark@gmail.com",
18 "user_status":1
19 },
20 {
21 "user_id":4,
22 "username":"Ville",
23 "user_email":"ville@gmail.com",
24 "user_status":0
25 }
26 ]
As you can see, it returns a list of users as a JSON object. Apart from that, if there’s any
application error, it would be returned as a JSON object as well for debugging purposes.