I can't really solve this for you because the problem could be anywhere, but you have some issues that should be resolved, hopefully some of what I am demonstrating will be useful:
1) If at all possible, use a framework instead, a lot of what you are doing is already solved (securely) by free frameworks. If you are dead-set on this:
2) Try to avoid using global
, you can inject the database instead:
cart($con);
3) Split out your functions a bit more, each function is doing too much:
# Try to make this more flexible by adding the limits as variables
# Also, you might decide that random is not a great idea, so this allows you
# to change that at each instance
# Also, if you leave the columns flexible, you will make your function that
# much more useful
function getProducts($con, $cols = '*', $page = 0, $limit = 6, $rand = true)
{
# Perhaps you don't want to limit one day
$limitSql = (!empty($page) || !empty($limit))? "LIMIT {$page}, {$limit}" : "";
# This allows you to insert an array and only select certain columns
$cols = (is_array($cols))? implode(", ", $cols) : $cols;
# Only add the randomness if you want to (default is to randomize)
$sql = ($rand)? "ORDER BY RAND()" : '';
# Create your dynamic statement
$stmnt = "SELECT {$cols} FROM products {$sql} {$limitSql}";
$query = mysqli_query($con, $stmnt);
# Have this just assemble the values, don't echo anything
while ($result = mysqli_fetch_array($query)) {
$row[] = $result;
}
# Send back the results
return (!empty($row))? $row : [];
}
Using this function:
# This would give you results with just the two columns with 10 results, no random
$products = getProducts($con, array("product_id", "product_title"), 0, 10, false);
# This should just return the count
$products = getProducts($con, "COUNT(*) as count", false, false, false);
So, now that you have this function, you write the loop in the view:
<?php foreach(getProducts($con, 'product_id') as $row): ?>
<!-- Now you have only pulled the one column required for this use -->
<a href="index.php?add_cart=<?php echo $row['product_id'] ?>">Add to Cart</a>
<?php endforeach ?>
4) This cart function is more problematic, it has a few issues. a) You need to bind parameters if your values from the user are not numeric, what you have is an sql injection and is a security issue b) You should split this function into two, c) You should leave the echoing outside in the view. d) If you are storing carts by ip, I would maybe not do that, more than one computer can have the same ip if they are using a VPN or on the same network. A cookie may be a better solution:
function itemExists($con, $pid, $ip)
{
$stmnt = "SELECT * FROM cart WHERE ip_add = '{$ip}' and p_id = '{$pid}'";
$query = mysqli_query($con, $stmnt);
return (mysqli_num_rows($query) > 0);
}
function addToCart($con, $pid, $qty = 1)
{
# Since you aren't binding, you need some sort of safeguard here, I am assuming
# your product id values are numeric. If not, you definitely need to bind parameters
if(!is_numeric($pid))
return false;
# Same here, you need to make sure nothing but numbers get through (or bind)
if(!is_numeric($qty))
$qty = 1;
# Pass on your connection and pid, inject the getIp() function if you choose
# to keep using it
$itemExists = itemExists($con, $pid, getIp());
# Confirm the item has no row in database
if($itemExists)
# Stop if it does
return false;
# You may want to echo here to see if this is what you expect
$stmnt = "insert into cart(p_id, ip_add) values ('{$pid}', '{$ip}')";
# I use PDO, but I am sure you can get an error back on this if the sql
# fails for whatever reason, that is a good place to start for your issue
$query = mysqli_query($con, $stmnt);
# Run this again to make sure it inserted
return itemExists($con, $pid, getIp());
}
Now in your view:
if(!empty($_GET['add_cart'])) {
# When you add to cart, there should be some feed back to whether it was successful
$success = addToCart($con, $_GET['add_cart']);
# If not you can echo it
if(!$success)
echo '<div class="msg error">An error occurred adding item to cart.</div>';
}
Anyway, hopefully this is useful, but you should think about 1) using a framework and if not, then use the OOP version of mysqli (or PDO) because the binding of parameters is much easier (I find) than the functional mysqli library.