Overview

In this tutorial we want to build a backend service, that can be called from a browser or a front end and pass back data to the user. The data it passes back will be stored on our database that we will build, for example this could be a list of customers. This is a bit of an advanced tutorial where we will implement four key concepts via the first hand approach. I will do my best to keep things as straight forward as I can, we are going to cover PHP, REST messaging, JSON data interchange and managing a mySQL database.

Even although there are a lot of things going on, all the steps are here and I will give a high level overview in this paragraph then we will just get straight to it. The main goal is for us to create an API that is able to perform full create, read, update and delete functions (CRUD) on a database. Our database is where we will store our customer information using phpmyadmin a built in database tool that runs on your local server or online one.
The process of communicating with our API is using REST which essentially has four main states (which is defined by the URL affix) you will see more about this later. In our API, we will make use of all REST states POST, PUT, GET and Delete which will also be linked to our database operations of Add, Update, Retrieve and Delete records respectively.
If at anytime you get stuck, please reference the my support code that can be found here. Also there are earlier versions of my code labelled restfulldemopt1 and pt2. Ok, lets get started!

Installing the required Software

Composer

You can get Composer here however the main issue here is actually getting composer to work (if you use mac). After running the suggested terminal script like below, you should try to input the command composer to see if it actually works.


If the response is bash command not found, then find the composer.phar file and try to run the following command.

$ mv composer.phar /usr/local/bin/composer

Now you need to install a platform that will allow you to set up a server on your own computer (Apache), to work with PHP and use PEARL. This can be done by installing either WAMP, MAMP or XAMP these are specifically for Windows, Mac and Linux respectively. Although XAMP now runs on all three operating systems. The link can be found here

The next step is to download an extension that allows you to initiate RESTful requests, this is a great way for debugging your API once set up. You can constantly fire in requests to add, delete, read and update data from your DATABASE provided by your API, this can be customer information, stock quantity etc. To do this its best to download RESTeasy extension on chrome. Simply click the apps icon in your chrome nav bar, go to the web store and enter RESTeasy in the search.It is offered by resteasy.venuedistrict.com and is a ‘developers tool’.

File Creation

To get started go ahead and create a file in your htdocs folder of your XAMP/WAMP/MAMP directory. You can do this via normal finder/window method, but to get practice with terminal do the following.

cd /applications/xampp/htdocs

Now lets create our new folder
mkdir demo

First set up a folder structure like the below, don’t worry about the ‘vendor’ file, this gets created in a later step when you install slimphp from command line. DEMO is the main folder directory, public is where the user comes into, and there is a .htaccess file which we will insert some code to help shorten our URL. SRC directory, has a config folder where we contain our database settings, routes is where we contain our actual script for processing customers.

Install SLIMPHP and Create Our Home Script

Next in order to add our vendor files (including the libs that lets us handle JSON) we should download a PHP tool, slimPHP, the easiest way to do this is to run the suggested command from the SlimPHP site for mac and the current script its

composer require slim/slim "^3.0"

Now its time to start creating some files, I am using sublime to do my coding and file creation but you can use brackets notepad ++ or many others. In the DEMO folder, create an index.php this is where the main php scripts are going to be written and paste in the example from slimphp website in getting started.

When we create a restful API we create routes that deal with requests and response objects, that is what we are doing in the first two lines, we are dealing with the request/response objects. So every SLIM application/route is given these object as the argument for the call back routine. SLIM supports PSR7 the php standard for messaging, a great approach for writing apps. Autoload.php is created by composer and allows us to refer to SLIM dependencies. $app-> allows us to create our route. in this case its /hello/name
We then compose the response and return it. Finally we need to do the run command at the end to make it actually work. In our case we modify the require statement to add ../ as we are in the sub directory.

Starting and Stopping Your Server

In order to run our php pages on a server, and navigate to them via the browser we need to start our servers. Locate the XAMPP application and click start all servers. This can be a tricky step as sometimes the severs don’t start due to other applications using port 80, alternatively you can run sudo lsof -i -P | grep -i "listen" this should output open ports any problems just drop me a message. Once you are ready go ahead and open up a browser and put in

http://localhost/slimapp/public/index.php/hello/bob

Bob can in fact be any name due to the way the code is set up, have a look at your index script to make sure you understand what is happening .

ACCESS TO OMIT INDEX.PHP PATH

We don't want to include the index.php every time so we will use a ht access file, additionally to omit the xxpubicxx part of the URL, we can add a virtual host in Apache.

 
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
	
Add a .htaccess file, add this code and save in the public folder. Now try out your hyperlink and omit the index.php to see if it works by going to http://localhost/demo/public/hello/bob

Adding virtual host - Enable Virtual hosts

I am actually having trouble with making this work myself, but if you want to try then first thing you’ll need to do is open the file /Applications/XAMPP/xamppfiles/etc/httpd.conf in your favourite text editor. Look for the following lines:

 
# Virtual hosts
#Include /Applications/XAMPP/etc/extra/httpd-vhosts.conf
	
Uncomment the second line, next add Virtual Hosts which can be found at conf >> extra>>httpd-vhosts.conf or /Applications/XAMPP/xamppfiles/etc/httpd.conf on the mac. Note make sure this isn't the folder with the tag original, that is just a backup in case the httpd file is corrupted or mistakes are made. Follow the steps in the help link provided in the httpd.conf doc, and once you are happy you have set up your virtual host, you need to go to the hosts document and add the host database. Either way be very careful in this process as its easy to cause problems to your server.

Point to a Working Directory

Now we are going to modify our main index.php file so it points to our customer script, this is where we will perform our main part of our work. Note once you do this, your original URL you used for returning hello/name will no longer work Follow the step below

In our customers php file, lets add the following and run the code by navigating to it in the browser as shown in the example below

Navigate path to run the code is http://localhost/demo/public/api/customers once loaded into the browser you should see the text CUSTOMERS printed to the screen

Create a Database

The whole point of building this API is so we can store information on a database and allow customers/ front end users to interact with it via the service API we provide. Lets create a bare bones database. First log into http://localhost/phpmyadmin you should see a screen like the following

Click on new, and create your database, lets call it demo for now, now create a table called customers with 10 columns. We may not actually need 10 columns, but myphpadmin is smart enough to allocate what we need. The first column should be called id, it should have A.I ticked and click ok, also have it as length 11. For the other 9 rows, go with

first_name
last_name
phone
email
address
city
district
This GUI is rather self intuitive but if you have any issues I have included a copy of the SQL package you can upload.

Connect to a Database

DEMO has no native data database wrappers so we will use PHP, specifically PDO which are PHP data objects (info can be found here) . This is an alternative to mySQLI, here you can find the connection documentation which you may need to reference when learning about setting up connections to your database, for now we can use my example. Now its time to set up your database configuration, its worth reading up on how this all works, but I have included my code sample for a starter, note that you will need to configure user/passwork/database name accordingly. If you are doing something different from my steps, then this can be quite an in-depth process so please contact me if you have any issues.

After the DB.PHP config has been set we need to add it in our main php file.

Test Connection String

Add a reference to the database in the main index.php script below the autoload require clause like so


require '../vendor/autoload.php';
require '../src/config/db.php'; 

now open up the URL http://localhost/demo/public/api/customers if you see any errors, then there is an issue with connecting to the database and you may need to trouble shoot your user/password/host settings.

Using PHP and PDO

Before we go to creating statements, here are some tips on using PHP with PDO standards, remember there is also links to the documentation provided in the ‘connect to a database’ section above. To create a variable, we use the $ sign, applying a function like connect looks like this.

$db->connect();
We create statements like this
  
$stmt = $db->query($sql);
$customers = $stmt->fetchAll(PDO: :FETCH_OBJ);

												
In general...
	// when we are working with PDO we need to create statements 
	// there are a few benefits to creating prepared statements
	// 1. the query only needs to be parsed once 
	// 2. can be executed multiple times with the same / or diff peramaters
	// 3. the parameters don't need to be quoted.

Retrieve customer information as JSON

Now its time to writes some code that will pull customer information from our database . Instead of doing an echo of CUSTOMERS text, we want to add an SQL variable that selects all from our database. This will be executed in a try/catch step, the modified code looks as follows.

 
//Get All Customers 

$app->get('/api/customers', function(Request $request, Response $response){
	$sql = "SELECT * FROM customers";

		try{
			// Get DB object 
			$db = new db();
			// connect 
			$db = $db->connect(); 
			// when we are working with PDO we need to  create statements 
			// there are a few benefits to creating prepared statements
			// 1. the query only needs to be parsed once 
			// 2. can be executed multiple times with the same / or diff peramaters
			// 3. the parameters don't need to be quoted. 
			//stmt is standard 
			// passes in $sql var


			$stmt = $db->query($sql);
			$customers = $stmt->fetchAll(PDO::FETCH_OBJ);
			$db = null;
			echo json_encode($customers);


		} catch(PDOException $e){
			//e for errors exception handling
       		 echo '{"error": {"text": '.$e->getMessage().'}';
    	}
});
I understand there is a lot of new things we added, including the SQL so please look through the code to familiarize yourself, if you are struggling to understand then start by reading up on basic sql, then php DB connection examples. Call the same URL http://localhost/demo/public/api/customers and you should now see the record outputted into the screen .

Interrogate API with RestEasy

It is time to treat our code like a professional API backend and interrogate it the proper way, with a front end mockup. Open RESTeasy application and follow the steps shown in the screen shot below.


If it works you will see 200 which means that everything is OK! Well done! This is a big step, you have effectively managed the core functionality of your API, now we simply add more features to the process, such as the full CRUD service of create, read, update and delete.

Retrieve a Single Customer from Database

So far so good! Again there is a lot of code that would take another tutorial to explain, so for this purpose it will be to get us up and running, I advise revisting the code for a deeper study afterwards. Copy the get all customers code and paste below, first change the route to point to the id as follows

 
//Get A SINGLE CUSTOMER 
//****All customers terms changed to customer, except in SQL statement
$app->get('/api/customer/{id}', function(Request $request, Response $response){
	$id = $request->getAttribute('id');

	$sql = "SELECT * FROM customers WHERE id = $id"; //$id comes from the URL 

		try{
			// Get DB object 
			$db = new db();
			// connect 
			$db = $db->connect(); 


			$stmt = $db->query($sql);
			$customer = $stmt->fetchAll(PDO::FETCH_OBJ); // changed to singular
			$db = null;
			echo json_encode($customer);  // changed to singular


		} catch(PDOException $e){
			//e for errors exception handling
       		 echo '{"error": {"text": '.$e->getMessage().'}';
    	}
});
These steps simply allow the database to fish out one record which matches the user input. Now lets use the Resteasy front end to call our API, note we need to change the url, as we amended in the code. This time its not customers in the URL, it is customer, followed by a number (which related to the ID) as shown below.


Note if we change id to 2, we can pull back the second customer from the database, more specifically, the customer whose ID relates to number 2.

Add a Customer

Now we want to add a customer, here is the add customer code to adde below in your customers.php file.

 
// Add Customer
//we need to get the parameters, usually these would be thru a form, instead of get attribute which is the url
	// if now we want to get param
$app->post('/api/customer/add', function(Request $request, Response $response){
    $first_name = $request->getParam('first_name');// GETS PARAMETERS FROM USER INPUT
    $last_name = $request->getParam('last_name');
    $phone = $request->getParam('phone');
    $email = $request->getParam('email');
    $address = $request->getParam('address');
    $city = $request->getParam('city');
    $district = $request->getParam('district');
    $sql = "INSERT INTO customers (first_name,last_name,phone,email,address,city,district) VALUES
    (:first_name,:last_name,:phone,:email,:address,:city,:district)";
    try{
        // Get DB Object
        $db = new db();
        // Connect
        $db = $db->connect();
        $stmt = $db->prepare($sql);
        $stmt->bindParam(':first_name', $first_name);  // BIND EACH PARAMATER
        $stmt->bindParam(':last_name',  $last_name);
        $stmt->bindParam(':phone',      $phone);
        $stmt->bindParam(':email',      $email);
        $stmt->bindParam(':address',    $address);
        $stmt->bindParam(':city',       $city);
        $stmt->bindParam(':district',      $district);
        $stmt->execute();
        echo '{"notice": {"text": "Customer Added"}';
    } catch(PDOException $e){
        echo '{"error": {"text": '.$e->getMessage().'}';
    }
});
Now we want to actually execute this with our front end using the GET request instead of the post request. Do the following add to the headers, content-type and call the value application/json.

here is some example code to try to add into the database.
 
{
	"first_name" : "Stacey",
	"last_name" : "Hoffman",
	"phone" : "444-333-111-34",
	"email" : "stacy@gmail.com",
	"address" : "27 London St",
	"city" : "London",
	"district" : "center"

}
Remember to change the URL and set the method to post (since we are using the REST update functionality). An example is shown below.


If performed correctly, you should see a response message saying customer added in the JSON response. You can reload the database to check, and it should look like something below.

CHALLENGE Try to pull back the newly added customer using the get a single customer method.

Finishing the project

Now all that is left to complete the CRUD operation of being able to update and delete a customer. Try to do this one on your own, however if you have managed to get this far please contact me for the full source code if you are struggling - as it contains the update and delete steps. A huge congratulations for attempting this tutorial, if you were able to get to the stage where you can interrogate your API by either the URL or rest easy then you have in a sense built a back end, you have also built and managed a database. Many thanks for all your efforts and I will be adding more content as well as a more in depth tutorial on these concepts.


Adam McMurchie 1/May/2017