json web service tutorial

SBSP

Senior Member
Joined
Sep 7, 2007
Messages
667
Reaction score
16
Hi Please help me out. I want to understand how to build a web service api.

I'm a bit lost with terminology. Do I have the following right.
Restful = returns data in json format and there are no other speciffics that makes it a restfull web service ?
SOAP = same as above but instead of json it returns the format in XML , the only specifics that makes it a valid SOAP envelope is in the header ?

I haven't touched on SOAP yet , I'm starting with json due to trend people seem to prefer restful ?

I'm using a purchase order document as my example.
Its has a header, detail and ship to location and i created 3 classes for the header,detail and ship to that will hold the values of each field.

See below. (please focus on the the method i used to return the data and ignore the un-escapped security risks)
My Biggest question is the detail part of the deader which is a nested array of data with-in the header

If you look at the last 2 object properties of the header class.

Code:
public $PO_DETAIL;
public $PO_SHIP_TO;

Is the above the correct way of using it ? Not I have to work backward by returning the sub arrays first before the root in order to make
php's json_encode() to parse it correctly.

Code:
<?php
/*
PHP JSON Web-Service response tutorial
*/

if(!empty($_GET["username"])){$Username = $_GET["username"];}else{$Username='NONE';}
if(!empty($_GET["password"])){$Passowrd = $_GET["password"];}else{$Passowrd='NONE';}

if($Username=='username' && $Passowrd=='password')
{

$PO_Detail[0] = new po_detail_data();
$PO_Detail[0]->ITEM_NUMBER="0000001A12dC";
$PO_Detail[0]->ITEM_DESC="NEMA 17 Stepper motor";
$PO_Detail[0]->QTY_ORDERED="12";
$PO_Detail[0]->UNIT_PRICE="75235.00";

$PO_Detail[1] = new po_detail_data();
$PO_Detail[1]->ITEM_NUMBER="0000202B13dC";
$PO_Detail[1]->ITEM_DESC="NEMA 17 Stepper Driver";
$PO_Detail[1]->QTY_ORDERED="12";
$PO_Detail[1]->UNIT_PRICE="75235.00";

$PO_SHIP_TO = new po_ship_to();
$PO_SHIP_TO->ADDR_NAME='Company on the moon';
$PO_SHIP_TO->ADDR_COUNTRY='Moon';
$PO_SHIP_TO->ADDR_STATE='Darkside';
$PO_SHIP_TO->ADDR_CITY='Centurion';
$PO_SHIP_TO->ADDR_SUBURB='3 Craters';
$PO_SHIP_TO->ADDR_CONTACT_NAME='Sarah Kerrigan';
$PO_SHIP_TO->ADDR_CONTACT_TEL1='000 000 0000';
$PO_SHIP_TO->ADDR_CONTACT_TEL2='000 000 0000';
$PO_SHIP_TO->ADDR_1='Base 1';
$PO_SHIP_TO->ADDR_2='Pod2';
$PO_SHIP_TO->ADDR_3='';

$PO_head = new po_header_data();
$PO_head->PO_NUMBER="PO0023456";
$PO_head->PO_REFERENCE="Test Ref";
$PO_head->PO_DESC="Test Desc";
$PO_head->POST_DATE="2018-10-12";
$PO_head->PO_DETAIL=$PO_Detail;
$PO_head->PO_SHIP_TO=$PO_SHIP_TO;


header('Content-type: application/json');
echo json_encode($PO_head);
}
else
{
    echo 'Username or password is incorrect';
}

class po_header_data
{
    public $PO_NUMBER;
    public $PO_REFERENCE;
    public $PO_DESC;
    public $POST_DATE;    
    public $PO_DETAIL;
    public $PO_SHIP_TO;
}
class po_detail_data
{
    public $ITEM_NUMBER;
    public $ITEM_DESC;
    public $QTY_ORDERED;
    public $UNIT_PRICE;    
}
class po_ship_to
{
    public $ADDR_NAME;
    public $ADDR_COUNTRY;
    public $ADDR_STATE;
    public $ADDR_CITY;    
    public $ADDR_SUBURB;
    public $ADDR_1;
    public $ADDR_2;
    public $ADDR_3;
    public $ADDR_CONTACT_NAME;
    public $ADDR_CONTACT_TEL1;
    public $ADDR_CONTACT_TEL2;
    
}


?>

Below is the results,
Am I doing anything wrong or is it the correct way of creating a web service ?

json.png
 
REST != JSON

JavaScript Object Notation (JSON) is a way to serialise/encode an object for transmission over the wire. Same with XML. Not that this is the sole purpose of XML. Both give us a means to encode an object’s state for transmission to another party so that the other party can create an instance of that object in the same state. Objects that are used to communicate information between parties are called DTOs (https://en.m.wikipedia.org/wiki/Data_transfer_object). A DTO is usually a simple class with default constriuctor and public property getters and setters so that the serialization process can read all properties and encode them into a transmittable format. Also the deserialisation process uses the default constructor to create the object on the receiving side and then uses the public property setters to set the object state from the over the wire representation. DTOs usually have no behaviour. Their sole purpose is to carry data.

REST (https://en.m.wikipedia.org/wiki/Representational_state_transfer) REST is a collection of concept defining how we access resources on the web. See the link for good info.

REST also defines how you structure a resource address. If you use HTTP (which is mostly the case), you use typical HTTP URI structure for the address and HTTP verbs to define the operations. HTTP GET to get the resource (like SQL SELECT). HTTP PUT to add a resource (like SQL INSERT), HTTP POST to update a resource (SQL UPDATE) and HTTP DELETE verb to delete a resource (like SQL DELETE). A REST URI will typically have the form:
<base url>/ResourceType/
<base url>/ResourceType/ResourceIdentifier

For example to get a list of purchase orders your back-end needs to handle a HTTP GET request to the address
<base url>/api/purchaseOrder

To get a specific PO you may use an HTTP GET to
<base url>api/purchasrOrder/<PO identifier>

To create a new PO you will issue a HTTP PUT to
<base url>/api/purchaseOrder
ThE request payload will contain the data in JSON/XML that provides the info for the backend to create the new PO. I.e. the payload is a serialised/encoded DTO.

To delete a specific PO you will issue a HTTP DELETE to
<base url>api/purchasrOrder/<PO identifier>

The URL scheme and payloads are largely left up to you to design. Obviously you need to provide documentation wrt URIs for the resources and structure of payloads. You can also use Swagger to make all this discoverable.
 
@Spacerat has you covered on the theory; so I'll try to fill in the remaining gaps with a fairly quick example of how to get your first PHP REST web api up and running.


Prerequisites

Fat-Free Framework:
...is a micro framework that helps simplify the development of among other things; web APIs, which you can download here: https://fatfreeframework.com/3.6/home

Database with a table populated with some data.
For the example I have used the sakila test database provided by MySQL, hosted on a local MySQL instance. The sakila test database (if you want it) can be download here: https://dev.mysql.com/doc/sakila/en/sakila-installation.html

MySQL community edition can be downloaded from here: https://dev.mysql.com/downloads/mysql/


The Fat-Free Framework, or simply F3, folder structure is as follows:

Basically you just unzip the F3 download and add the files\folders to your project root folder.



Creating your REST web API in PHP:
PHP:
// Kickstart the framework
$f3 = require 'lib/base.php';

// Load configuration
$f3->config('config.ini');

// Create a route for your web API including a filter parameter for `actor_id`
$f3->route('GET /api/actor/@id', function ($f3) {
    $id = $f3->get('PARAMS.id');
    $mysqlpdo = new \PDO("mysql:dbname=sakila;host=127.0.0.1", "root", "password");
    $sql = "select * from actor where actor_id='" . $id . "'";
    $result = $mysqlpdo->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
    if ($result) {
        echo json_encode(array("actors" => $result));
    } else {
        echo json_encode(array("actors" => "failed..."));
    }
    $mysqlpdo = null;
});


Accessing from your browser:
chrome.png
Note:
  • I have one of my PHP instances virtually mapped to port 8003, so just substitute 8003 with the port you're using.
  • As for PHP frameworks; there are many; the reason I specifically chose F3 for the example is because it's simple, fast and easy to set-up.
 
Last edited:
Also, depending on which browser you use, there are extensions that will auto format JSON to make it easier to read.
 
Quickly setting it up I don't quite get the web service base setup right .htaccess always confuses me a bit.








I can confirm the database is setup and working by altering [)roi(] example a bit.



Its returning the sample data fine.

returned.png

When I replace the fatFree index.php file with the sample provided by [)roi(] it doesn't actually return anything.



Looks like i have to read up on .htaccess AGAIN! :-)
 

Attachments

  • folderstruct.png
    folderstruct.png
    30.8 KB · Views: 9
  • sample.png
    sample.png
    70.2 KB · Views: 9
  • viewsource.png
    viewsource.png
    18.4 KB · Views: 8
Thanks I will take a look at that. Im using apache from the xampp stack.
 
Thanks I will take a look at that. Im using apache from the xampp stack.
Good, then just follow the notes for apache & .htaccess; restart apache and everything should work.
BTW The .htaccess that came with F3 already has these mods.
 
Also from your images; I see that you are executing the index.php from a sub-folder jsonWebservertest of your web server's root : htdocs, so you either need to add a rewrite rule for that, for example:
Code:
RewriteBase /jsonWebservertest/
...or better yet set it up as a separate virtual host, listening on a different local port.
Code:
// add this to allow apache to also listen on a different port
Listen 8001

// Add this to set-up a virtual host for that 8001 port
<VirtualHost *:8001>
    #ServerName www.example.com
    DocumentRoot "c:\xampp\htdocs\jsonWebservertest"
    <Directory "c:\xampp\htdocs\jsonWebservertest">
        Options -Indexes +FollowSymLinks +Includes
        AllowOverride All
        Order allow,deny
        Allow from All
    </Directory>
</VirtualHost>

Access the site with http://127.0.0.1:8001/
 
Top
Sign up to the MyBroadband newsletter
X