This topic is locked

How to insert master and multiple details via REST API call

8/18/2025 6:34:18 PM
PHPRunner Tips and Tricks
Sergey Kornilov admin

This was a part of the recent DevClub webinar. In this article we will expalin how to implement a custom REST API that would allow to insert multiple records into several tables at once. We will use orders as master table that has to details tables, order details and users.

img alt

The following code goes to AfterAppInit event of your project. It accepts data in JSON format and also performs a basic authentication against a hardcoded API key. A more robust approach would be to store API in the database and you can have a separate API key for diffeent API users.

Note: this code assumes that master table's primary key column is auto-increment.

// insert order with details
if(postvalue("apidata") ){

// authentication
$authkey = "1234567890";
if($_SERVER['HTTP_AUTH']!=$authkey){
echo "Authenticate error";
exit();
}

$out = my_json_decode(postvalue("apidata"));

// process master table data
$mastertable = $out["mastertable"];
$data = $out["data"];
DB::Insert($mastertable, $data);
$err = DB::LastError();
if($err){
echo $err;
exit();
}

// master table id
// master table primary field must be autoincrement
$master_id = DB::LastId();

$details = $out["details"];

// process details table data one by one
foreach($details as $name=>$value){
$detailtable = $value["detailtable"];
$data = $value["data"];
$masterkey = $value["masterkey"];
$data[$masterkey] = $master_id;
DB::Insert($detailtable, $data);
$err = DB::LastError();
if($err){
echo $err;
exit();
}
}
echo "ok";
exit();
}

And here is a content of a PHP file that you can use for API testing purposes. You can create a new file under Style Editor -> Custom Files named apitest.php. After you built your project you can run it in the web browser as http://localhost:8086/apitest.php. If the URL of your application is different you also need to adjust it at the top of this file.

<?php
require_once("include/dbcommon.php");
$url = "http://localhost:8086/menu.php";
$res["mastertable"]="orders";
$res["data"] = array();

// master table data ( Orders)
$data = array();
$data["CustomerID"]="10";
$data["EmployeeID"] = "12";
$data["OrderDate"] = date("Y-m-d");
$res["data"] = $data;

// Order details table
$res["details"] = array();
$details = array();
$details["detailtable"] = "order details";
$details["masterkey"] = "OrderID";
$details["data"] = array();
$data = array();
$data["ProductID"] = 1;
$data["UnitPrice"] = 10;
$data["Quantity"] = 2;
$details["data"] = $data;
$res["details"][] = $details;
$data["ProductID"] = 2;
$data["UnitPrice"] = 24;
$data["Quantity"] = 1;
$details["data"] = $data;
$res["details"][] = $details;
$data["ProductID"] = 3;
$data["UnitPrice"] = 100;
$data["Quantity"] = 3;
$details["data"] = $data;
$res["details"][] = $details;
$data["ProductID"] = 4;
$data["UnitPrice"] = 3;
$data["Quantity"] = 15;
$details["data"] = $data;
$res["details"][] = $details;
$data["ProductID"] = 5;
$data["UnitPrice"] = 35;
$data["Quantity"] = 4;
$details["data"] = $data;
$res["details"][] = $details;

// second details table ( users )
$details["detailtable"] = "users";
$details["masterkey"] = "OrderID";
$details["data"] = array();
$data = array();
$data["username"] = "user1";
$data["password"] = "pass1";
$data["email"] = "email1";
$details["data"] = $data;
$res["details"][] = $details;
$data["username"] = "user2";
$data["password"] = "pass2";
$data["email"] = "email2";
$details["data"] = $data;
$res["details"][] = $details;
$str = json_encode($res);
$parameters["apidata"] = $str;

// authorization
$headers["auth"] = "1234567890";

// make a POST
$res = runner_post_request($url, $parameters, $headers);
if($res["error"])
echo $res["error"];
else
echo $res["content"];
exit();
?>

Once you run it, it will create a new order with five details and two associated users.

And, just in case here is a SQL script that creates required tabes in the database.

CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NULL,
`password` varchar(60) NULL,
`country` varchar(500) NULL,
`ext_security_id` longtext NULL,
`lat` decimal(32, 2) NULL,
`lng` decimal(32, 2) NULL,
`page` varchar(100) NULL,
`email` longtext NULL,
`apikey` varchar(50) NULL,
`two_factor` int NULL,
`table` varchar(50) NULL,
`group` varchar(50) NULL,
`timezone` varchar(100) NULL,
`reset_date` datetime NULL,
`reset_token` longtext NULL,
`ip` varchar(250) NULL,
`userpic` longblob NULL,
`phone` varchar(50) NULL,
`active` int NULL,
`OrderID` int NULL
);

CREATE TABLE `orders` (
`OrderID` int NOT NULL AUTO_INCREMENT,
`CustomerID` varchar(5) NULL,
`EmployeeID` int NULL,
`OrderDate` datetime NULL,
`RequiredDate` datetime NULL,
`ShippedDate` datetime NULL,
`ShipVia` int NULL,
`Freight` decimal(12, 2) NULL DEFAULT 0.00,
`ShipName` varchar(100) NULL,
`ShipAddress` varchar(60) NULL,
`ShipCity` varchar(15) NULL,
`ShipRegion` varchar(15) NULL,
`ShipPostalCode` varchar(10) NULL,
`ShipCountry` int NULL,
`Ended` int NULL,
`Archived` int NULL,
`ownerid` int NULL,
`Total` decimal(32, 2) NULL,
`agentid` int NULL,
PRIMARY KEY (`OrderID` )
);

CREATE TABLE `order details` (
`OrderID` int NOT NULL DEFAULT 0,
`ProductID` int NOT NULL DEFAULT 0,
`UnitPrice` decimal(12, 2) NOT NULL DEFAULT 0.00,
`Quantity` smallint NOT NULL DEFAULT 1,
`Discount` decimal(4, 3) NOT NULL DEFAULT 0.000,
`CategoryID` int NULL,
`OrderDetailsID` int NOT NULL AUTO_INCREMENT,
`Status` varchar(50) NULL,
PRIMARY KEY (`OrderDetailsID` )
);

Enjoy!