How would I make the $query_ppimage results a sub array from the first users query? At the moment, the output is outputting a user, then a profile image, under the user, rather than inside the users array. Therefore they aren't linked.
How would I do such a thing?
Here is my code:
$query_user = "SELECT *,'user' AS type FROM users WHERE username LIKE '".$query."' OR firstname LIKE '".$query."' OR lastname LIKE '".$query."'";
$quser = $conn->query($query_user);
$rows = array();
while($user = mysqli_fetch_assoc($quser)) {
$query_ppimage = "SELECT id, post_id, relation, userID, file_format FROM media WHERE userID = '".$user['id']."' AND relation = 'profile_picture' UNION ALL SELECT -1 id, '55529055162cf' post_id, 'profile_picture' relation, '0' userID, 'jpg' file_format ORDER BY id DESC";
$qppimg = $conn->query($query_ppimage);
while($ppimg = mysqli_fetch_assoc($qppimg)) {
$rows[] = $ppimg;
$rows[] = $user;
}
}
Here is how the array is returned:
[
{
"id": "117",
"post_id": "1",
"relation": "profile_picture",
"userID": "3",
"file_format": "jpg"
},
{
"id": "3",
"email": "casper#socialnetwk.com",
"type": "user"
},
]
How it should look, or something similar. I don't think I named the sub array correctly, but it needs a name ppimage
[
{
"id": "3",
"email": "casper#socialnetwk.com",
"type": "user"
ppimage: {
"id": "117",
"post_id": "1",
"relation": "profile_picture",
"userID": "3",
"file_format": "jpg"
}
},
]
You are adding to $rows twice and appending two separate elements. Try building your array element first and then adding it into the $rows array. Something like this:
$newrow = $user;
$newrow['ppimage'] = $ppimg;
$rows[] = $newrow;
Using JOIN, you could limit this to one single query. Having a query inside a loop is never a good idea, and you should avoid it if you can. Furthermore, you should use prepared statements in order to protect against SQL injection.
The code below uses a JOIN, so that you just get one query - and structures the array as shown in the example. This is hard-coded, as its easier to control what goes where, since we now use a JOIN, the data is all fetched at once (and not in separate variables).
$row = array();
$stmt = $conn->prepare("SELECT m.id, m.post_id, m.relation, m.file_format, u.id, u.email, 'user' as type
FROM media m
JOIN users u ON u.id=m.userID
WHERE m.relation = 'profile_picture'
AND (username LIKE ?
OR firstname LIKE ?
OR lastname LIKE ?)
ORDER BY m.id DESC");
$stmt->bind_param("sss", $query, $query, $query);
$stmt->execute();
$stmt->bind_result($mediaID, $postID, $relation, $file_format, $userID, $user_email, $type);
while ($stmt->fetch()) { // If you just expect one row, use LIMIT in the query, and remove the loop here
$row[] = array('id' => $userID,
'email' => $user_email,
'type' => $type,
'ppimage' => array('id' => $mediaID,
'post_id' => $postID,
'relation' => $relation,
'userID' => $userID,
'file_format' => $file_format)
);
}
$stmt->close();
How can I prevent SQL injection in PHP?
MySQL JOIN
Related
I have this db structure:
create table article(
id int AUTO_INCREMENT PRIMARY KEY,
title varchar(50),
text text
)
create table comments(
id int AUTO_INCREMENT PRIMARY KEY,
article int not null
username varchar(30) not null,
text text not null,
foreign key(article) references article(id) on delete cascade
)
I would like to get articles with comments and convert to json with this structure:
[
{
id: 1,
title: "article1",
text: "text1",
"comments": [
{
id: 1,
username: "user1",
text: "text"
}
]
}
]
This is my code:
$query = $pdo->query('select * from article as a join comments as c on c.article =a.id');
$query->execute();
var_dump(json_encode($query->fetchAll(PDO::FETCH_ASSOC)));
and result:
[{"id":"1","title":"artile1","text":"comment1","article":"1","username":"user1"}]
It is any way how to get article and comments as inner array? I could do it manually but, I will have a lot of tables with many columns.
Thanks for advices
It looks like it is not possible using PDO fetch modes. They are powerful, but unfortunately, I was not able to get the output you wanted.
You can achieve this outcome using a simple loop. The downside is that you have to create the array manually.
$stmt = $pdo->prepare('SELECT a.id AS aid, a.title, a.text AS atext, c.id AS cid, c.username, c.text AS ctext
FROM article AS a
JOIN comments AS c ON c.article =a.id ');
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$id = null;
$data = [];
foreach ($stmt as $row) {
$comment = [
'id' => $row['cid'],
'username' => $row['username'],
'text' => $row['ctext'],
];
if ($id == $row['aid']) {
// If parent ID still the same append only comment
$data[array_key_last($data)]['comments'][] = $comment;
} else {
// set new id and append a whole new row
$id = $row['aid'];
$data[] = [
'id' => $row['aid'],
'title' => $row['title'],
'text' => $row['atext'],
'comments' => [$comment]
];
}
}
PDO has plenty of fetch modes and you can mix them together, but it looks like none of them can cope with joins the way you would like them too. They are all described here in https://phpdelusions.net/pdo/fetch_modes
I currently have 2 tables no established relationships between the two. I just like to append the data from the 2nd table to the end of the 1st table in the JSON output.
1st table:
map_type map_value
-----------------------------
image_link www.google.com
top_lat 32.91
right_long -117.13
zoom_level 17.5
2nd table:
marker_name marker_lat marker_long
------------------------------------------
Food 32.91 -117.14
Party 31.22 -119.20
Chips 29.02 -120.00
I understand the basic query to join 2 tables, and implemented using the following code:
$sql = "select * from second_table join first_table";
$q = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
//create an array
$jsonData = array();
while($row = mysqli_fetch_assoc($q))
{
$jsonData[$row['map_type']] = $row['map_value'];
// Issue is here
if ( !isset($jsonData['markers'] ) )
{
$jsonData['markers'] = array();
}
array_push($jsonData['markers'],
array('marker_name'=> $row['marker_name'],
'marker_lat'=> $row['marker_lat'], 'marker_long'=> $row['marker_long']));
}
echo json_encode($jsonData);
As such, I get the following output:
{
"image_link": "www.google.com",
"markers": [{
"marker_name": "Food",
"marker_lat": "32.91",
"marker_long": "-117.14"
}, {
"marker_name": "Food",
"marker_lat": "32.91",
"marker_long": "-117.14"
},
...
}],
"top_lat": "32.91",
"right_long": "-117.13",
"zoom_level": "17.5"
}
The only data from the second table is the data contained in markers, while the other field data is from the first table.
The problem is in the comment labeled "Issue is here". Each marker entry in the second table is repeated 4 times, where 4 represents the number of fields in the first table.
I know I'm doing something wrong in that area, but I just started learning and trying to understand php better.
The output should look something like, where markers is appended to the end of the list, with the correct number of entries:
{
"image_link": "www.google.com",
"top_lat": "32.91",
"right_long": "-117.13",
"zoom_level": "17.5",
"markers": [{
"marker_name": "Food",
"marker_lat": "32.91",
"marker_long": "-117.14"
}, {
"marker_name": "Party",
"marker_lat": "31.22",
"marker_long": "-119.20"
}, {
"marker_name": "Chips",
"marker_lat": "29.02",
"marker_long": "-120.00"
}]
}
How can I achieve this output?
UPDATE: as #sepehr has explained, I understand the cause now and have replaced the code with the following to make 2 queries:
$sql = "select * from first_table";
$result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
$jsonData = array();
while($row =mysqli_fetch_assoc($result))
{
$jsonData[$row['map_type']] = $value;
}
$sql = "select * from second_table";
$result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
$index = 1;
while($rownew =mysqli_fetch_assoc($result))
{
$markers[$index] = array("marker_name" => $rownew['marker_name'], "marker_lat" => doubleval($rownew['marker_lat']), "marker_long" => doubleval($rownew['marker_long']) );
++$index;
}
$jsonData['markers'] = $markers;
echo json_encode ($jsonData);
This achieves the correct output, but can someone let me know if this is the most efficient and optimal way?
Those duplicates are because of that JOIN statement. It will produce duplicate rows. Have a look for yourself.
In order to build that json object, I suggest you executing two separate queries on those tables. Since they have no logical relation with each other.
Or if you MUST achieve this in one query, which I don't recommend, use a UNION like this to avoid those duplicate records.
Get the results from the 2 tables separately and merge them using the array_merge function.
$maps = array(); //get the result from table 1
$markers = array(); //get the result from table 2
$result = array_merge($maps,$markers);
echo json_encode($result);
I am trying to get a summed field in medoo.
My sql at the moment is like:
$database->debug()->select("user_rupees_in_house", [
"[<]rupees" => ["rupee_id" => "ID"]
], [
"name",
"amount",
"amount_spend"
], [
"user_uuid" => $user,
"GROUP" => "rupee_id"
]);
The debug logs the following statement:
SELECT `name`,`amount`,`amount_spend`, `rupee_id`
FROM `user_rupees_in_house`
RIGHT JOIN `rupees`
ON `user_rupees_in_house`.`rupee_id` = `rupees`.`ID`
WHERE `user_uuid` = '4da9ff11-56ca3a2f-b3ab-a25b9230'
GROUP BY `rupee_id`
What I'm trying to achieve is:
SELECT `name`,SUM(`amount`),SUM(`amount_spend`), `rupee_id`
FROM `user_rupees_in_house`
RIGHT JOIN `rupees`
ON `user_rupees_in_house`.`rupee_id` = `rupees`.`ID`
WHERE `user_uuid` = '4da9ff11-56ca3a2f-b3ab-a25b9230'
GROUP BY `rupee_id`
Does anybody know how to make this statement in medoo?
[EDIT 1]
Found another way of achieving this
// Get the rupee types
$rupee_types = $database->select("rupees", "ID");
foreach ($rupee_types as $rupee_type) {
$amount = $database->sum("user_rupees_in_house", "amount", [
"AND" => [
"rupee_id" => $rupee_type,
"user_uuid" => $user
]
]);
// Build array of rupees
}
This will make a lot more calls to the database, but is working just fine as long as the SELECT statement does not support aggregate functions.
Medoo doesn't support aggregate function in SELECT statement. Use raw query instead.
Try this:
$result = $database->query(
"SELECT `name`,SUM(`amount`),SUM(`amount_spend`), `rupee_id`
FROM `user_rupees_in_house`
RIGHT JOIN `rupees`
ON `user_rupees_in_house`.`rupee_id` = `rupees`.`ID`
WHERE `user_uuid` = '$user'
GROUP BY `rupee_id`"
)->fetchAll();
Reference
I'm building a Sencha-Touch 2 app and I have some trouble with the recuperation of my data from server side (mysql DB).
Here's my data model :
Table1 :
ID:int
description:varchar(100)
Table2 :
ID:int
description:varchar(100)
table1_ID:int
Table3 :
ID:int
name:varchar(100)
info:varchar(100)
table2_ID:int
Table1 is join to Table2 with a one-to-many relationship and same between Table2 and Table3.
What I want from server is a nested JSON who looks like this :
[
Table1_object1_ID: 'id' : {
Table1_object1_description: 'description',
Table2_Objects : [
'Table2_object1': {
Table2_object1_id : 'id',
Table2_object1_description : 'description'
Table3_Objects : [
table3_object1: {
Table3_object1_name : 'name',
Table3_object1_info : 'info',
},
table3_object2: {
Table3_object2_name : 'name',
Table3_object2_info : 'info',
},
table3_object3: {
Table3_object3_name : 'name',
Table3_object3_info : 'info',
},
etc...
],
},
'Table2_object2': {
Table2_object2_id : 'id',
Table2_object2_description : 'description'
Table3_Objects : [
...
]
},
etc....
]
},
Table1_object2_ID: 'id' : {
etc....
]
In my App, I use 3 Models for each Table, and ideally I want to save my data in 3 Stores, but that will be an other problem ;-)
The first Store (based on the Model from Table1) do a JsonP request to get the Nested JSON.
Actually my SQL request in the PHP file is simple :
SELECT *
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.table1_ID
INNER JOIN Table3 ON Table2.ID = Table3.table2_ID;
I tried to make an array in PHP from my SQL results but cannot get the expect result.
I also try to change my SQL with GROUP BY and GROUP_CONCAT but same here, cannot get the JSON I want.
Some help would be really appreciate.
Runnable code with some sample data: http://codepad.org/2Xsbdu23
I used 3 distinct SELECTs to avoid the unnecessary repetitions.
Of course you have to customize the $result array to your exact desired JSON format, but I think it is not that hard.
// assume $t1/2/3 will be arrays of objects
$t1 =
SELECT Table1.*
FROM Table1
WHERE Table1.ID = 111
$t2 =
SELECT Table2.*
FROM Table2
WHERE Table2.table1_ID = 111
$t3 =
SELECT Table3.*
FROM Table2
INNER JOIN Table3 ON Table2.ID = Table3.table2_ID
WHERE Table2.table1_ID = 111
function array_group_by( $array, $id ){
$groups = array();
foreach( $array as $row ) $groups[ $row -> $id ][] = $row;
return $groups;
}
// group rows from table2/table3 by their parent IDs
$p2 = array_group_by( $t2, 'table1_ID' );
$p3 = array_group_by( $t3, 'table2_ID' );
// let's combine results:
$result = array();
foreach( $t1 as $row1 ){
$row1 -> Table2_Objects = isset( $p2[ $row1 -> ID ]) ? $p2[ $row1 -> ID ] : array();
foreach( $row1 -> Table2_Objects as $row2 )
$row2 -> Table3_Objects = isset( $p3[ $row2 -> ID ]) ? $p3[ $row2 -> ID ] : array();
$result[] = $row1;
}
echo json_encode( $result );
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)"
}';