Before You Begin
Purpose
This tutorial shows you how to create a PHP REST API using an Oracle Database Cloud Service instance and deploy the application to Oracle Application Container Cloud Service. You also learn how to log errors and messages using STDOUT and how to get the logs from Oracle Application Container Cloud Service.
Time to Complete
40 minutes
Background
Representational state transfer (REST) is an architectural design for designing communication and operational channels among networked applications. The REST design is commonly implemented while building web HTTP APIs. As REST APIs interact through HTTP requests, they provide heterogeneous interoperability. RESTful APIs are best used when a single web page has to show data from multiple partners.
PHP is a popular general-purpose scripting language that is especially suited to web development. PHP can be used to develop the RESTful APIs or the clients to consume the APIs.
Scenario
In this tutorial, you build a basic RESTful API that implements the CRUD (Create, Read, Update, and Delete) operations on a employee table in a Oracle Database Cloud Service instance, using plain PHP without dependency on any framework.
The php RESTful application responds to the following endpoints:
| Path | Description |
|---|---|
| GET: /employees | Gets all the employees. |
| GET: /employees/{searchType}/{searchValue} | Gets the employees that match the search criteria. |
| POST: /employees | Adds an employee. |
| PUT: /employees/{id} | Updates an employee. |
| DELETE: /employees/{id} | Removes an employee. |
This tutorial covers
two ways to test your
RESTful API, one using
the Postman tool and
other using an HTML
Client. The HTML
client is provided in
the next section.
The zip file contains
a index.html
file and seven .png
images. This client is
developed using
JQuery, Ajax and CSS.
What Do You Need?
- An active Oracle Cloud account
- An instance and credentials of Oracle Database Cloud Service. See Oracle Database Cloud - Database as a Service Quick Start
- Oracle SQL Developer
- Postman
- employee-client.zip
- phpEmployeeAPI.zip (This is the PHP project with source code. Download it if you want to view the completed project.)
Setting Up the Database and the Objects
In this section, you create a connection to your Oracle Database Cloud Service instance from the Oracle SQL Developer and execute the scripts to create the employee table and the employee sequence.
Connecting Oracle SQL Developer to Your Database
-
Open Oracle SQL Developer.
-
Click the View menu and select SSH.
-
Right-click SSH Hosts and click New SSH Host...
Description of this image -
Enter the following information and click OK.
- Name:
- Host: Enter the public ip address of your Oracle Database Cloud Service instance.
- Username:
opc - Select Use key file.
- Click Browse and select the private key file.
- Select Add a local port forward.
- Name:
- Host:
localhost - Port:
1521 - Select Use
specific local
port
1523
Description of this image -
Right-click to the new host connection and click Connect.
Description of this image -
Enter the passphrase.
Description of this image -
Right-click Connections and select New Connection.
Description of this image -
In the New / Select Database Connection dialog box, enter values in the following fields, and then click Test:
- Connection Name
- Username
- Password
- Connection
Type:
SSH - Role:
default - Port
forward:
Local(DBCS) - Service name
Description of this image -
Click Save, and then click Connect.
Creating the Database Objects
-
Right-click the connection and select Open SQL worksheet.
Description of this image -
Copy the following script into the SQL worksheet to create the
EMPLOYEEtable and the sequence namedEMPLOYEE_SEQ:CREATE TABLE EMPLOYEE ( ID INTEGER NOT NULL, FIRSTNAME VARCHAR(255), LASTNAME VARCHAR(255), EMAIL VARCHAR(255), PHONE VARCHAR(255), BIRTHDATE VARCHAR(10), TITLE VARCHAR(255), DEPARTMENT VARCHAR(255), PRIMARY KEY (ID) ); CREATE SEQUENCE EMPLOYEE_SEQ START WITH 100 INCREMENT BY 1; -
Click Run Statement
and then click Commit
.
Building the REST Service
Creating a Resource Representation Class
In this section,
you create a class
named Employee
to represent the
state of the
employee objects
with the
properties: first
name, last name,
birth date, phone,
e-mail,
department, and
title.
-
Create a folder in your local system to contain all your project files.
-
Create a PHP class named
Employee.php. -
Add the following properties to define the employee objects.
public $id; public $firstName; public $lastName; public $birthDate; public $phone; public $email; public $dept; public $title; -
Add the
setmethod and save the file.public function set($arrayParams) { if (!empty($arrayParams['id'])) { $this->id = $arrayParams['id']; } $this ->firstName = $arrayParams['firstName']; $this->lastName = $arrayParams['lastName']; $this->birthDate = $arrayParams['birthDate']; $this->phone = $arrayParams['phone']; $this->email = $arrayParams['email']; $this->dept = $arrayParams['dept']; $this->title = $arrayParams['title']; }PHP doesn't have a way to automatically convert the JSON parameters to a custom object. The
setmethod will be useful to set the employee's properties with the JSON parameters from the request.
Creating the Persistence Layer
In this section,
you create the EmployeeStorage
class, that
contains the
methods to get,
save, update, and
delete the
employees data
from the database.
-
Create a PHP class named
EmployeeStorage.php. -
Include the
Employee.phpclass after the<?phptag.include("Employee.php"); -
Create the
private $connvariable and add the constructor.To create the connection to an Oracle Database Cloud Service instance from an application deployed in Oracle Application Container Cloud Service you can get the username, password, and connector descriptor from the environment variables (
DBAAS_USER_NAME, DBAAS_USER_PASSWORD,andDBAAS_DEFAULT_CONNECT_DESCRIPTOR). These variables are created when you add the database service binding, see the Adding the Database Service Binding section.private $conn; public function __construct() { $userName = getenv('DBAAS_USER_NAME') ? getenv('DBAAS_USER_NAME') : 'oracle'; $password = getenv('DBAAS_USER_PASSWORD') ? getenv('DBAAS_USER_PASSWORD') : 'oracle'; $default_descriptor = getenv('DBAAS_DEFAULT_CONNECT_DESCRIPTOR') ? getenv('DBAAS_DEFAULT_CONNECT_DESCRIPTOR') : 'localhost:1523/PDB1.smdev.oraclecloud.internal'; $this->conn = oci_connect($userName, $password, $default_descriptor); if (!$this->conn) { $e = oci_error(); trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR); echo "connection error. Failed....."; } } -
Add the methods
getAll, search, delete, update,andsave.public function getAll() { $data = Array(); $query = 'SELECT * FROM EMPLOYEE'; $stid = oci_parse($this->conn, $query); oci_execute($stid); while ($row = oci_fetch_array($stid, OCI_ASSOC + OCI_RETURN_NULLS)) { $employee = new Employee(); $employee->id = $row['ID']; $employee->firstName = $row['FIRSTNAME']; $employee->lastName = $row['LASTNAME']; $employee->phone = $row['PHONE']; $employee->birthDate = $row['BIRTHDATE']; $employee->title = $row['TITLE']; $employee->dept = $row['DEPARTMENT']; $employee->email = $row['EMAIL']; array_push($data, $employee); } return $data; } public function search($criteria, $value) { $data = Array(); if ($criteria=='department'){ $filter = 'DEPARTMENT'; }else if ($criteria=='lastname'){ $filter = 'LASTNAME'; }else if ($criteria=='title'){ $filter = 'TITLE'; }else{ throw new Exception('Filter criteria not valid'); } $query = 'SELECT * FROM EMPLOYEE WHERE ' . $filter . '=:value'; $stmt = oci_parse($this->conn, $query); oci_bind_by_name($stmt, ':value', $value, -1); oci_execute($stmt); while ($row = oci_fetch_array($stmt, OCI_ASSOC + OCI_RETURN_NULLS)) { $employee = new Employee(); $employee->id = $row['ID']; $employee->firstName = $row['FIRSTNAME']; $employee->lastName = $row['LASTNAME']; $employee->phone = $row['PHONE']; $employee->birthDate = $row['BIRTHDATE']; $employee->title = $row['TITLE']; $employee->dept = $row['DEPARTMENT']; $employee->email = $row['EMAIL']; array_push($data, $employee); } return $data; } public function delete($id) { $query = 'DELETE FROM EMPLOYEE WHERE ID = :id'; $stmt = oci_parse($this->conn, $query); oci_bind_by_name($stmt, ':id', $id, -1); oci_execute($stmt); } public function update($employee) { $query = 'UPDATE EMPLOYEE SET FIRSTNAME=:firstName, LASTNAME=:lastName, PHONE=:phone, BIRTHDATE=:birthdate, TITLE=:title, DEPARTMENT=:department, EMAIL=:email ' . 'WHERE ID=:id'; $stmt = oci_parse($this->conn, $query); oci_bind_by_name($stmt, ':firstName', $employee->firstName); oci_bind_by_name($stmt, ':lastName', $employee->lastName); oci_bind_by_name($stmt, ':phone', $employee->phone); oci_bind_by_name($stmt, ':birthdate', $employee->birthDate); oci_bind_by_name($stmt, ':title', $employee->title); oci_bind_by_name($stmt, ':department', $employee->dept); oci_bind_by_name($stmt, ':email', $employee->email); oci_bind_by_name($stmt, ':id', $employee->id); oci_execute($stmt); } public function save($employee) { $query = 'INSERT INTO EMPLOYEE (ID, FIRSTNAME, LASTNAME, EMAIL, PHONE, BIRTHDATE, TITLE, DEPARTMENT) ' . 'VALUES(employee_seq.nextval,:firstName,:lastName,:email,:phone,:birthdate,:title,:department)'; $stmt = oci_parse($this->conn, $query); oci_bind_by_name($stmt, ':firstName', $employee->firstName); oci_bind_by_name($stmt, ':lastName', $employee->lastName); oci_bind_by_name($stmt, ':phone', $employee->phone); oci_bind_by_name($stmt, ':birthdate', $employee->birthDate); oci_bind_by_name($stmt, ':title', $employee->title); oci_bind_by_name($stmt, ':department', $employee->dept); oci_bind_by_name($stmt, ':email', $employee->email); oci_execute($stmt); }
Creating the RESTful Web Service Controller
In this section, you create the php routine to process the HTTP requests and return the JSON response.
- Create a PHP
file named
employees-rest-api.php -
Include the
EmployeeStorage.phpclass after the<?phptag.include("EmployeeStorage.php"); -
Define STDOUT for use with fwrite.
-
Add the
$verbvariable to store the request method using the$_SERVERarray.$verb = $_SERVER['REQUEST_METHOD']; -
Create the
$url_piecesarray to hold the pathname information.$url_pieces = explode('/', $_SERVER['PATH_INFO']); -
Limit the support requests to
/employeesand throw an exception if is not.if ($url_pieces[1] != 'employees') { throw new Exception('Unknown endpoint', 404); } -
Add the following code to process the different request methods (
GET, POST, PUT, DELETE,andOPTIONS):$employeeStorage = new EmployeeStorage (); $data; switch ($verb) { case 'GET': $filter; $value; if (!empty($url_pieces[2])) { $filter = $url_pieces[2]; $value = $url_pieces[3]; $data = $employeeStorage->search($filter, $value); } else { $data = $employeeStorage->getAll(); } break; case 'POST': $params = json_decode(file_get_contents("php://input"), true); if (!$params) { throw new Exception("Data missing or invalid"); } $employee = new Employee(); $employee->set($params); $employeeStorage->save($employee); $data = '{"status":"OK"}'; http_response_code(201); break; case 'PUT': $params = json_decode(file_get_contents("php://input"), true); if (!$params) { throw new Exception("Data missing or invalid"); } $id; if (!empty($url_pieces[2])) { $id = $url_pieces[2]; } $employee = new Employee(); $employee->id = $id; $employee->set($params); $employeeStorage->update($employee); $data = '{"status":"OK"}'; http_response_code(200); break; case 'DELETE': $id; if (!empty($url_pieces[2])) { $id = $url_pieces[2]; $employeeStorage->delete($id); } $data = '{"status":"OK"}'; http_response_code(200); break; case 'OPTIONS': http_response_code(200); $data = '{"status":"OK"}'; break; default: throw new Exception('Method Not Supported', 405); }When we send a request thought AJAX using the methods:
POST, PUT,andDELETEa verification request is made to the server. This request uses theOPTIONSmethod and sends the headers to determine whether or not it will allow requests of this type. If the response is OK then the real request(POST, PUTorDELETE)is sent. This is the reason why theOPTIONSmethod is implemented. -
Add the following headers to support cross-domain requests.
header("Content-Type: application/json"); header('Access-Control-Allow-Origin:*'); header('Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT, PATCH, DELETE'); header('Access-Control-Allow-Headers:X-Requested-With,content-type'); header('Access-Control-Allow-Credentials:true'); -
Print the
$dataarray using thejson_encodemethod.echo json_encode($data); -
Close STDOUT file descriptor.
fclose(STDOUT);
Adding the HTML Client
In this section, you
add the client files
to your project and
you update the index.html
file to connect the
client to your RESTful
application.
Extract the contents of the employee-client.zip
file in the root
directory of your
project.
Note:
Make sure the index.html
is in the root
directory of your
project.
Preparing the Application for Cloud Deployment
When you upload your
application to Oracle
Application Container
Cloud Service using
the user interface,
you must include a
file called manifest.json
in the application
archive (.zip,
.tgz, .tar.gz
file). If you use the
REST API to upload the
application, this file
is still required but
doesn’t have to be in
the archive.
The manifest.json
file specifies the PHP
version to use and
optionally, you can
include notes and
application-specific
release information.
-
Create the
timer.shscript file to simulate an application log.while true; do echo 'date'; sleep 5; done -
Create the
start.shscript file and add the following content:# Fork background process that writes to time.log to simulate an application # log one might want to monitor touch time.log sh ./timer.sh > time.log & # Tailing a file of interest will sent its contents to stdout which is captured # by ACCS tail -f time.log & # Launch Apache Server to start serving up our PHP application--this is only # necessary because we provided a start command in the manifest.json apache2-run -
Create the
manifest.jsonand add the following content:{ "runtime": { "majorVersion": "7.1" }, "command": "sh ./start.sh", "notes": "PHP REST Sample Application" } -
Compress the project files (including the
.phpfiles, theindex.html, and the images), the script files(start.sh,andtimer.sh), and themanifest.jsonfile in a file namedphpEmployeeAPI.zip.
Description of this image
Deploying the Application to Oracle Application Container Cloud Service
In a web browser, go to https://cloud.oracle.com/home and click Sign In.
From the Cloud Account menu, select Traditional Cloud Account, select your data center, and click My Services.
Enter your identity domain and click Go.
Enter your cloud account credentials and click Sign In.
- In the Oracle Cloud My Services dashboard, click Action
, click Services, and select Application Container. -
In the Applications page, click Create Application, and select PHP.
Enter a name for your application, select Upload Archive, and click Browse.
-
In the File Upload dialog box, select the
phpEmployeeAPI.zipfile that you created in the previous section, and click Open. In the Create Application dialog box, keep the default values and click Create.
Description of this image
Adding the Database Service Binding
-
In the Applications page, click your application.
Description of this image -
Click the Deployments tab and in the Service Binding section, click Add.
Description of this image -
In the Add Service Binding dialog box, select Database Cloud Service in the Service Type field, enter or select values in the Service Name, Username, and Password fields. Click Save.
Description of this image -
In the Application page, click Apply Edits.
Description of this image -
In the Apply Changes dialog box, click Restart.
- Click Applications.
On the Applications page, the application apaas-deploy-release-rolling status is displayed until the deployment is complete.
Testing the REST Service
Testing the RESTful API with the Postman Tool
-
Open the Postman tool.
-
Select the POST method and enter the URL of your RESTful API.
Note: Replace <identity-domain> with the entity domain of your cloud account.
URL:
https://employees-api-<identity-domain>.apaas.us2.oraclecloud.com/employees-rest-api.php/employees -
Click the Body tab, select raw, then select the JSON(application/json) format, enter the following body request, and click Send.
{"firstName":"Laura", "lastName":"Jones", "email":"laura.jones@example.com", "phone":"1203123", "birthDate":"1975-05-14", "title":"Developer Manager", "dept":"IT"}
Description of this image -
Select the GET method and click Send.
Description of this image -
Select the PUT method, add the ID of the new employee to the end of the URL:
https://employees-api-<identity-domain>.apaas.us2.oraclecloud.com/employees-rest-api.php/employees/100 -
Click Body and enter the following request body:
{"firstName":"Laura", "lastName":"Jones", "email":"laura.jones@example.com", "phone":"1203123", "birthDate":"1975-05-14", "title":"Manager", "dept":"Sales"}
Description of this image -
Execute the GET request again.
You can see the new value of
titleanddept.
Description of this image -
Select the DELETE method and click Send.
Description of this image You can execute the GET method again to verify the employee is deleted.
Testing the RESTful API with the HTML Client
-
Click the URL to open your application.
Description of this image -
Click Add New.
Description of this image -
Fill the form and click Add.
Description of this image -
Select the card of the new employee.
Description of this image -
Click Edit.
Description of this image -
Change the value of the Department field and click Update.
Description of this image The employee card is updated.
Description of this image -
Click the card of the employee and click Delete.
Description of this image -
Click Delete and then click Ok to confirm.
Description of this image
Description of this image
Getting the logs
-
Open the Oracle Application Container Cloud Service console.
-
Select your application.
Description of this image -
Click Administration. and then click Logs
Description of this image -
Click Get Log
. -
Select the Instance from which you want get the logs.
Description of this image -
Wait a minute, and click then Refresh
. -
Click the log file you want to download.
Description of this image In the Save As dialog box, select a location for the zip file, and click Save.
Extract the contents of the zip file and open the
server.outfile in a text editor.
Want to Learn More?
- Oracle Application Container Cloud Service Get Started in the Oracle Help Center
-
PHP website php.net