DISCLAIMER: Before I continue I would like to state that I am not a PHP pro or anything like that, I haven't even touched PHP for 3-4 years (where then I knew way more) which makes it even harder for me to understand the issue, I've been looking online but didn't get far sadly so I decided to post a question here
P.S: About my code, I know that better SQL methods can be used but as it stands for now I just want to figure out what is wrong with my code and then I can take care of "improving" it
I know that I am probably approaching this in the wrong way (at first I thought its only my sql query)
Code:
<?php
header('Access-Control-Allow-Origin: localhost');
header('Content-type: application/json');
$conn = mysqli_connect("localhost", "root", "local_database", "example_db");
// Pull Member data
function getMember($data) {
try {
$select = mysqli_query($conn, "SELECT * FROM store_members WHERE name = '{$data}'");
$result = mysqli_fetch_assoc($select);
mysqli_free_result($select);
} catch (RuntimeException $e) {
$result["error"] = "Error: ".$e->getMessage();
}
return $result;
}
// Function that takes 2 strings and tries to find a match against a list, if a match is found it will be returned.
// Example Usage: (1) echo InGroupID(1, "2, 8", "10, 3, 8"); (2) echo InGroupID(10, "2, 8", "10, 3, 6"); (3) echo InGroupID(10, "2, 8", "10, 3, 8"); || (1) Result: 8, (2) Result: 10 (3) Result: 10
function InGroupID($maingroup, $secondary_groups = FALSE, $customgrouplist = FALSE) {
$member->split_sgroups = preg_split("/[\s,]+/", $secondary_groups);
$groups->permitted = array(4, 2, 6); // 4 = Admins, 2 = Moderators, 6 = Private Users (default list if none provided)
if($customgrouplist !== FALSE)
$customgrouplist = preg_split("/[\s,]+/", $customgrouplist);
else
$customgrouplist = $groups->permitted;
$sgroup_match = array_intersect($member->split_sgroups, $customgrouplist);
$key = array_search($maingroup, $customgrouplist);
if($key !== false)
return $customgrouplist[$key];
elseif(($secondary_groups !== FALSE) && ($sgroup_match !== FALSE)) {
sort($sgroup_match);
return $sgroup_match["0"];
}
else
return false;
return false;
}
$query = mysqli_query($conn, "SELECT * FROM `store_products`");
$res = array();
if(mysqli_num_rows($query) >= 1) {
$mmbr = getMember("Admin");
while($row = mysqli_fetch_assoc($query)) { // duplicates results for me, if I disable the first while it will display products based only on permissions from 1 row and not accordingly to each product
$getGroup = InGroupID($mmbr["main_group_id"], $mmbr["secondary_group_ids"], $row["product_permissions"]); // tries to find a match for members permissions in store products, if found, the match will be returned so we can use it to filter products in the next while.
$cQuery = mysqli_query($conn, "SELECT `product_name`,`price`,`quantity`,`product_permissions` FROM `store_products` WHERE CONCAT(',', product_permissions, ',') like '%{$getGroup}%'"); // product_permissions example "5, 9, 10"
// SELECT `product_name`,`price`,`quantity` FROM `store_products` WHERE FIND_IN_SET('{$getGroup}',product_permissions) -> this won't work for values after the first comma because it is seperated by comma and space and not just comma
if(!empty($getGroup)) {
while($row2 = mysqli_fetch_assoc($cQuery)) { // if 1st while is off it will display rows based on matching permissions from first row only and not each accordingly
$row2["price"] = intval($row2["price"]);
$row2["quantity"] = intval($row2["quantity"]);
// Debug, can be ignored.
$row2["main_group_id"] = $mmbr["main_group_id"];
$row2["secondary_group_ids"] = $mmbr["secondary_group_ids"];
$row2["($)getGroup"] = $getGroup;
$res[] = $row2;
}
}
}
echo json_encode($res);
}
else {
$res[0] = array(
"product_name" => "no_products_available_foruser",
"price" => 0,
"quantity" => 0
);
echo json_encode($res);
}
SQL Tables Used:
TABLE store_members
:
+-----------------------------------------------------------------+
| store_members |
+----+-----------+----------+---------------+---------------------+
| id | name | password | main_group_id | secondary_group_ids |
+----+-----------+----------+---------------+---------------------+
| 1 | Admin | --- | 4 | 8 |
+----+-----------+----------+---------------+---------------------+
| 2 | Moderator | --- | 2 | 8, 3 |
+----+-----------+----------+---------------+---------------------+
| 3 | VIP_User | --- | 8 | 3 |
+----+-----------+----------+---------------+---------------------+
| 4 | Shopper12 | --- | 3 | NULL |
+----+-----------+----------+---------------+---------------------+
TABLE store_products
:
+--------------------------------------------------------------------------+
| store_products |
+----+----------------------------+-------+----------+---------------------+
| id | product_name | price | quantity | product_permissions |
+----+----------------------------+-------+----------+---------------------+
| 1 | iPhone X - VIP Edition | 30 | 5 | 4, 2, 8 |
+----+----------------------------+-------+----------+---------------------+
| 2 | iPhone X - Public | 45 | 200 | 2, 8, 3 |
+----+----------------------------+-------+----------+---------------------+
| 3 | iPhone X - Private Edition | 15 | 3 | 4, 2 |
+----+----------------------------+-------+----------+---------------------+
| 4 | Pixel 4 - VIP Edition | 28 | 10 | 4, 2, 8 |
+----+----------------------------+-------+----------+---------------------+
| 5 | Pixel 4 - Private Edition | 12 | 8 | 4, 2 |
+----+----------------------------+-------+----------+---------------------+
| 6 | Pixel 4 - Public | 42 | 164 | 2, 8, 3 |
+----+----------------------------+-------+----------+---------------------+
| 7 | Pixel 4 - Subscribers | 40 | 100 | 6 |
+----+----------------------------+-------+----------+---------------------+
Here's what the code should do basically,
Short Version:
Pulls product list from an sql table store_products
by a users group id/sub group ids from store_members
table and displays the list in json.
Long Version:
PHP Script to get main_group_id
, secondary_group_ids
values from store_members
table by a given members name
and then takes main_group_id
, secondary_group_ids
and searches for any match at another table (store_products
) at column product_permissions
finally, if there's a match the certain product will be displayed, it should search for a match for every product separately from store_products
and then display it in json.
The Problem: Duplicated results, here's how it happens to me -
Let's get the product list for user "Admin" in a json file, Member Properties - Name: Admin , Main Group ID: 4 (Admins) , Secondary Group IDS: 8 (VIP)
A while loop should calculate how many rows to display based on permission match for each row individually, For example My Main Group ID & Secondary Group IDS are 4 and 8 which means I have permissions to view products list for groups 4 and 8, I should get 6 results then because 4 and 8 exist in these rows product_permissions
, Instead I get duplicate results and I sometimes don't get products that match permission for my subgroup, especially for products that have two of my groups in their product_permissions
It's all calculated like that:
InGroupID(4, 8, "4, 2, 8"); // 4 (my main group), 8 (secondary), iPhone X - VIP Edition's `product_permissions` || returns 4 because there is a match for 4 in 4,2,8 (first match gets returned first)
InGroupID(4, 8, "2, 8, 3"); // 4 (my main group), 8 (secondary), iPhone X - Public's `product_permissions` || returns 8 because there is a match for 8 in 2,8,3 (first match gets returned first)
The match from InGroupID
will be passed to $getGroup
through an SQL query (SELECT `product_name`,`price`,`quantity`,`product_permissions` FROM `store_products` WHERE CONCAT(',', product_permissions, ',') like '%{$getGroup}%'
) and will loop with while
for each product in the list to display accordingly
Notice: The Enteries below appear at the json file and are just for "debugging" purposes to better understand the problem, ignore them if you'd like as they are not a part of the actual code.
"product_permissions": "X, X, X",
"main_group_id": "X",
"secondary_group_ids": "X, X",
"($)getGroup": "X"
Default Output (original code): https://codebeautify.org/jsonviewer/cb675fd3 - shows all results but has too many duplicates
Without the 1st while-loop (// while($row = mysqli_fetch_assoc($query)) {
): https://codebeautify.org/jsonviewer/cbebc3eb
Expected Output (what I wanted): https://codebeautify.org/jsonviewer/cb656906
Can you tell me what's wrong with my code?