Insert Data from a JSON to MySQL database table - php

I am trying to insert data to 2 different tables in my database.
First table is named business which I have done it to insert data to from the json file to the database.
But when I am trying to insert data into table named business_phone it does not do anything.
Here is my code for inserting the data:
$query = '';
$query_phones='';
$table_data = '';
$filename = "businesses.json";
$businesses = file_get_contents($filename);
$business = json_decode($businesses, true);
foreach($business as $row)
{
$query .= "INSERT INTO business(title, address, website, page) VALUES ('".$row["title"]."', '".$row["address"]."', '".$row["website"]."', '".$row["page"]."'); ";
//data that i will show on page
$table_data .= '
<tr>
<td>'.$row["title"].'</td>
<td>'.$row["address"].'</td>
<td>'.$row["website"].'</td>
<td>'.$row["page"].'</td>
</tr>
';
}
foreach($business as $row)
{
$query_phones .="INSERT INTO business_phones(business_title, phone_number, phone_name) VALUES ('".$row["title"]."', '".$row["number"]."', '".$row["name"]."');";
}
Here is some code from the json file
[
{
"title": "CONSERVE IT LTD",
"address": "12 Truman Ave (10) ",
"phones": [
{
"name": "telephone_1",
"number": "876-754-0220"
},
{
"name": "telephone_2",
"number": "876-754-0221"
}
],
"website": "www.conserveitja.com",
"page": 1
},
{
"title": "Consie Walters Cancer Hospital",
"address": "22 Deanery Rd (3) ",
"phones": [
{
"name": "telephone_1",
"number": "876-930-5016"
}
],
"page": 1
},
...
]

I don't know how you to handle within php but you can create an auxiliary table to be populated from the file, and then use JSON_TABLE function for the key values to be inserted into that table, provided you're using MySQL DB ver. 8+ :
INSERT INTO business(title, address, website, page)
SELECT t.*
FROM tab
CROSS JOIN
JSON_TABLE(jsdata, '$[*]' COLUMNS (
title VARCHAR(100) PATH '$.title',
address VARCHAR(100) PATH '$.address',
website VARCHAR(100) PATH '$.website',
page VARCHAR(100) PATH '$.page')
) t
and
INSERT INTO business_phones(business_title, phone_number, phone_name)
SELECT t.*
FROM tab
CROSS JOIN
JSON_TABLE(jsdata, '$[*]' COLUMNS (
business_title VARCHAR(100) PATH '$.title',
NESTED PATH '$.phones[*]' COLUMNS (
phone_number VARCHAR(100) PATH '$.number',
phone_name VARCHAR(100) PATH '$.name')
)
) t
a side Note concatenations for sql statements are vulnerable to Injection for most of the programming languages as #Magnuss Eriksson mentioned.
Demo

$row["number"] is not valid. It will be $row["phones"][0] or $row["phones"][1]. Because according to your data "number" and "name" inside of "phones" which is array.
You can nested loop through "phones"
foreach($row["phones"] as $contact){
$query .="INSERT INTO business_phones(business_title, phone_number,
phone_name) VALUES ('".$row["title"]."', '".contact."',
'".$row["name"]."');"
}

Related

SQL query JSON of MySQL 8.0 comes String instead of Array

I create a table in MySQL 8.0 as follows:
CREATE TABLE `airline_table` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`info` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
It contains JSON type data, and I insert some data as:
INSERT INTO airline_table VALUES ('1','{"data": [{"city": "Houston", "state": "TX"},
{"city": "Los Angles", "state": "CA"}], "airline": ["UA", "AA"]}');
And I use php to visit the database, I wish to get value of "airline" as an Array.
<?php
$mysqli = new mysqli("localhost", "root", "aproot2019", "test");
$sql = "SELECT id, info -> '$.airline' AS airline FROM airline_table";
$result = $mysqli->query($sql);
$row = $result->fetch_array();
//print_r($row);
$airline = $row['airline'];
echo $airline . "<br>"; // ["UA", "AA"] , this is a string but not an array, how can I have an Array?
echo is_array($airline) ? 'Array' : 'not an Array' . "<br>"; // not an Array
echo is_string($airline) ? 'String' : 'not a String' . "<br>" ; // String
$mysqli->close();
?>
But it comes out a String, NOT an Array!
This really annoys me, and JSON in MySQL is hard to understand.
Have you considered decoding JSON?
$json = json_decode('{"data": [{"city": "Houston", "state": "TX"}, {"city": "Los Angles", "state": "CA"}], "airline": ["UA", "AA"]}');
// for your case it will be :
// $json = json_decode($row['airline']);
echo var_dump($json->airline);
/**
* array(2) {
[0]=>
string(2) "UA"
[1]=>
string(2) "AA"
}
Querying a JSON from MySQL is not hard, but.... For this kind of tables I would not do it in JSON. 😉
SELECT
j.city,
j.state
FROM airline_table
CROSS JOIN JSON_TABLE(info, '$.data[*]' COLUMNS(
city VARCHAR(20) PATH '$.city',
state VARCHAR(20) PATH '$.state')) as j
output:
city
state
Houston
TX
Los Angles
CA

Add Data from JSON in database in two different tables

I have a JSON file which contains data that i want to store in two different database in sql.
The json file looks like this:
[
{
"title": "CONSERVE IT LTD",
"address": "12 Truman Ave (10) ",
"phones": [
{
"name": "telephone_1",
"number": "876-754-0220"
},
{
"name": "telephone_2",
"number": "876-754-0221"
}
],
"website": "www.conserveitja.com",
"page": 1
},
{
"title": "Consie Walters Cancer Hospital",
"address": "22 Deanery Rd (3) ",
"phones": [
{
"name": "telephone_1",
"number": "876-930-5016"
}
],
"page": 1
},
...
]
I managed to store title, address, website and page in my 1st table in the database but now I want to store in a different table in the same database the phones for each business.
Here is the code I am using to store the information for the first table and I little code for the 2nd table.
$connect = mysqli_connect("localhost", "root", "1234", "businesses"); //Connect PHP to MySQL Database
$query = '';
$query_phones='';
$table_data = '';
$filename = "businesses.json";
$businesses = file_get_contents($filename);
$business = json_decode($businesses, true);
foreach($business as $row)
{
$query .= "INSERT INTO business(title, address, website, page) VALUES ('".$row["title"]."', '".$row["address"]."', '".$row["website"]."', '".$row["page"]."'); ";
//data that i will show on page
$table_data .= '
<tr>
<td>'.$row["title"].'</td>
<td>'.$row["address"].'</td>
<td>'.$row["website"].'</td>
<td>'.$row["page"].'</td>
</tr>
';
}
Code for inserting the phone data in the second table in database
foreach($business as $row)
{
$query_phones .="INSERT INTO business_phones(business_title, phone_number, phone_name) VALUES ('".$row["title"]."', '".$row["number"]."', '".$row["name"]."');";
}
Structure of 1st table (business)
1 idPrimary int(11)
2 title varchar(50)
3 address varchar(50)
4 website varchar(50)
5 page int(11)
Structure of 2nd table (business_phones)
1 idPrimary int(11)
2 business_title varchar(250)
3 phone_number varchar(255)
4 phone_name varchar(255)

Convert MySQL group concat string to json object structure via PHP

I have 2 MySQL tables, the first one is the parent table and second one the child table. These two table share a 1:M relationship. The T_1 contains the list of unique users with some informations. And the T_2 contains all the line data list with coordinates at a specific timestamp for each user. The child table T_2 has a FK that references the PK in the T_1 parent table. I share below the CREATE STATEMENT:
CREATE TABLE `T_1` (
`id` varchar(45) DEFAULT NULL,
`value_1` tinyint(4) NOT NULL,
`personId` varchar(45) NOT NULL,
`value_2` varchar(45) NOT NULL,
`value_3` varchar(45) NOT NULL,
`Value_4` int(11) NOT NULL,
PRIMARY KEY (`personId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `T_2` (
`personId` varchar(45) NOT NULL,
`timestamp` varchar(45) NOT NULL,
`x` int(11) NOT NULL,
`y` int(11) NOT NULL,
KEY `user_fk_idx` (`personId`),
CONSTRAINT `user_fk` FOREIGN KEY (`personId`) REFERENCES `T_1` (`personId`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I would like to get as final json result something like that:
[
{
"id": "",
"value_1": true,
"personId": "1",
"value_2": "test",
"value_3": "test",
"value_4": 10,
"lineData": [
{
"timestamp": "some_date",
"x": 100,
"y": 250
},
{
"timestamp": "some_date",
"x": 100,
"y": 350
}
]
},
{
"id": "",
"value_1": true,
"personId": "2",
"value_2": "test",
"value_3": "test",
"value_4": 10,
"lineData": [
{
"timestamp": "some_date",
"x": 50,
"y": 450
},
{
"timestamp": "some_date",
"x": 80,
"y": 550
}
]
}
]
This is the first query selection that I have made in order to get the aggregation of all the T_2 records for each T_1.personId:
SELECT T_1.personId,GROUP_CONCAT(CONCAT(T_2.timestamp, T_2.x, T_2.y) SEPARATOR ' ')
FROM T_1
JOIN T_2
ON T_1.personId=T_2.personId
GROUP BY personId;
Except that I need to add also id, value_1, value_2, value_3, value_4, the query aggregation seems correct by I'm still far away from the expected result:
By using the PDO::FETCH_ASSOCquery fetch within PHP I get actually the similar expected array result.
But the main problem is that the linedata aggregation is just in a single string format grouped and concatenated all together, not in an object structure form. (screen below)
I attach the example data below from the query selection:
array(7) {
["id"]=>
NULL
["value_1"]=>
string(1) "0"
["personId"]=>
string(2) "1"
["value_2"]=>
string(9) "test"
["value_3"]=>
string(4) "test"
["value_4"]=>
string(2) "10"
["linedata"]=>
string(359) "2018/09/15 10:00:05 AM1100950 2018/09/15 10:00:07 AM1100850 2018/09/15 10:00:09 AM1180800 2018/09/15 10:00:10 AM1280800 2018/09/15 10:00:15 AM1380800 2018/09/15 10:00:17 AM1480800 2018/09/15 10:00:20 AM1900800 2018/09/15 10:00:25 AM1930750 2018/09/15 10:00:40 AM1910440 2018/09/15 10:00:45 AM1250460 2018/09/15 10:01:25 AM1100455 2018/09/15 10:01:29 AM1100655"
}
}
Maybe is it needed to concatenate the square and curly brackets within the selection query?
Can someone suggest me how to get the correct separated structure for linea data? I supposed that we need to use also some post-process PHP stuff in order to get the exact desired output structure.
Update
Following the #Salman A's suggestion, I have tweak the query as below:
GROUP_CONCAT(CONCAT_WS(', ',timestamp,x, y) SEPARATOR '; ') as linedata_0
And I have stored the result of the query within $query_result.
Then I have made a nested foreach in order to explode each row with ; and each value of each row with , in $query_result['linedata_0']. And I have put the exploded result in a new key called linedata_1. As showed below:
foreach ($query_result as $q_r){
$first_split = explode(";", $q_r["linedata_0"]);
foreach ($first_split as $f_s){
$second_split = explode(",", $f_s);
$query_result["linedata_1"][]= $second_split;
}
}
I have removed the $query_result[0]["linedata_0"] element. And after that I have assigned the key values to each $query_result['linedata_1'] sub-arrays and store in a new element called $query_result['linedata']. After that I have remove the old $query_result['linedata_1'] element with unset command and in the last foreach I have cast the x and y values from string to integer:
unset($query_result[0]["linedata_0"]);
foreach(($query_result["linedata_1"]) as $q_r) {
$keys = array('timestamp', 'x', 'y');
$query_result["linedata"][] = array_combine($keys, $q_r);
}
unset($query_result["linedata_1"]);
$index = 0;
foreach($query_result["linedata"] as $index=>$val) {
$query_result["linedata"][$index]["x"] = (int) $val["x"];
$query_result["linedata"][$index]["y"] = (int) $val["y"];
$index++;
}
With these PHP post-process operations I got exactly the expected result.Probably this post-process steps within php are not well optimized, but they do the trick for me. If someone of us has a more optimized workaround solution please share it. Thanks.

Merge 2 different tables without repeating values PHP

I have 2 tables; the first one is user_in_event table
which here role can be regular, waiting for ack or moderator
and the second one is user table
Here the role can be regular or admin
I want to take the role from user_in_event table, based on the event_id and output all users info (beside user role) and output in a single JSON
I have tried to use LEFT JOIN
$query = "SELECT user_in_event.role, user_in_event.user_id, user.name, user.email, user.birthday, user.phone_number, user.address, user.image
FROM user LEFT JOIN user_in_event
ON user_in_event.event_id = '".$event_id."'
LIMIT $num_of_rows";
$result = mysqli_query($con,$query)
or die(mysqli_error($con));
// print_r($query);
while ($row = mysqli_fetch_assoc($result)) {
$response[] = $row;
}
header('Content-Type:Application/json');
echo json_encode($response);
but I got messed up data
[
{
"role": "moderator",
"user_id": "2",
"name": "ofir",
"email": "ofir#ofr.com",
"birthday": "08/12/2016",
"phone_number": "123",
"address": "yoqneam",
"image": "http://imgur.com/a/KslOW"
},
{
"role": "waiting for ack",
"user_id": "21",
"name": "ofir",
"email": "ofir#ofr.com",
"birthday": "08/12/2016",
"phone_number": "123",
"address": "yoqneam",
"image": "http://imgur.com/a/KslOW"
}
]
PS: I also tried to make 2 different queries and combine the JSON and user array_merge_recursive but I got 2 subs arrays instead of a single one
Please try :
SELECT user_in_event.role, user_in_event.user_id, user.name, user.email
FROM user
LEFT JOIN user_in_event ON user_in_event.user_id = user.user_id
WHERE user_in_event.event_id =25
LIMIT 0 , 30
Here event_id is static. run this query to your database and let me know.

fql.multiquery returning empty array

I'm am trying to query all the photo albums of a page and get each albums cover photo. Below is the code I have that returns an empty result.
I am able to make both the queries separately without the problem, so it is not a permissions issue.
$album_fql = "SELECT aid, owner, name, object_id, cover_pid, cover_object_id
FROM album
WHERE owner = 'xxxxxxx'";
$albumpic_fql = "SELECT pid, src_small
FROM photo
WHERE pid IN (SELECT cover_pid FROM #query1)";
$album_param = array(
'method' => 'fql.multiquery',
'queries' => '{"query1":"' . $album_fql . '", "query2":"' . $albumpic_fql . '"}');
$album_fqlResult = $facebook->api($album_param);
print_r($album_fqlResult);
Any ideas?
you can do that in a nested query rather than as a multi query.
SELECT pid, src_small
FROM photo
WHERE pid in (SELECT cover_pid FROM album where owner={page id here})
for example here's the list of album covers I got from CocaCola's Facebook page
SELECT pid, src_small
FROM photo
WHERE pid in (SELECT cover_pid FROM album where owner=40796308305)
LIMIT 5
returned:
{
"data": [
{
"pid": "40796308305_2143765",
"object_id": 110516463305,
"src_small": "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-snc1/6570_110516463305_40796308305_2143765_6253354_t.jpg"
},
{
"pid": "40796308305_8753877",
"object_id": "10150500888203306",
"src_small": "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/398389_10150500888203306_40796308305_8753877_1814220329_t.jpg"
},
{
"pid": "40796308305_8751674",
"object_id": "10150500434253306",
"src_small": "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/407475_10150500434253306_40796308305_8751674_1040781388_t.jpg"
},
{
"pid": "40796308305_8742570",
"object_id": "10150498588158306",
"src_small": "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/396541_10150498588158306_40796308305_8742570_1378170213_t.jpg"
},
{
"pid": "40796308305_8742259",
"object_id": "10150498546173306",
"src_small": "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-snc7/402667_10150498546173306_40796308305_8742259_287537096_t.jpg"
}
]
}
If you want to try your multiquery, then try to name the queries starting at index 0 instead of 1. e.g. query0 and query1 This is the only way the C# SDK allows it, maybe the php SDK requires that too.
Finally figured it out. I had to merge the queries into 1 variable and escape the single quotes.
$queries = '{
"query1" : "SELECT aid, name, cover_pid FROM album WHERE owner = \'xxxxxxxxxxx\'",
"query2" : "SELECT aid, images FROM photo WHERE pid IN (SELECT cover_pid FROM #query1)"
}';

Categories