I'm new to php and I'm trying to add items to my DB table (cart) but when I click on 'add to cart' nothing happens. The button is displayed through the function getPro, which is below.
function cart(){
if(isset($_GET['add_cart'])){
global $con;
$ip = getIp();
$pro_id = $_GET['add_cart'];
$check_pro = "SELECT * FROM cart where ip_add='$ip' and p_id='$pro_id'";
$run_check = mysqli_query($con, $check_pro);
if(mysqli_num_rows($run_check)>0){
echo "";
}
else {
$insert_pro = "insert into cart(p_id,ip_add) values ('$pro_id','$ip')";
$run_pro = mysqli_query($con, $insert_pro);
echo "<script>window.open('index.php','_self')</script>";
}
}}
Add to cart button is echoed by this function.
function getPro(){
global $con;
$get_pro = "select * from products order by RAND() LIMIT 0,6";
$run_pro = mysqli_query($con, $get_pro);
while ($row_brand_pro=mysqli_fetch_array($run_pro)) {
$pro_id = $row_brand_pro['product_id'];
$pro_cat = $row_brand_pro['product_cat'];
$pro_brand = $row_brand_pro['product_brand'];
$pro_title = $row_brand_pro['product_title'];
$pro_price = $row_brand_pro['product_price'];
$pro_image = $row_brand_pro['product_image'];
echo "
<a href='index.php?add_cart=$pro_id'><button style='float:right;'>Add to Cart</button></a>
</div>
";
}
}
}
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 -->
Add to Cart
<?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.
Related
In symfony and Doctrine i am using the session to save a query result then later on i am filtering this result with some parameters.
The problem is that once the parameters are changed i can't get the original results set. Here is the code
fetching results and saving to session
$query = $this->getDoctrine()->getManager()->createQueryBuilder();
$query->select("sp")
->from("CoreBundle:ServiceProvider","sp")
->innerJoin("sp.offers","offer")
->innerJoin("offer.service","service","with","offer.service = service")
->innerJoin("sp.firstImage","fi")
->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
->orderBy("sp.points" ,"DESC")
->addOrderBy("sp.name" ,"ASC");
$queryAndFilters = $this->getFilters($query,$postData);
$query = $queryAndFilters['query'];
$filters=$queryAndFilters['filters'];
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query, /* query NOT result */
$pageNumber,
20/*limit per page*/
);
$query = $query->getQuery();
$query->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true);
$this->get('session')->set("results",$query->getResult());
and then in another function
filtering the results
$results = $this->get('session')->get("results");
$filteredResults = array();
// print_r(array_keys($results[0]));
foreach($results as $result){
$sp = $result;
foreach($sp->getOffers() as $offer){
// echo "found offer ".$offer->getName()." with price ".$offer->getPrice()."<br />";
$sp->removeOffer($offer);
if($offer->getPrice() < $minPrice || $offer->getPrice() > $maxPrice){
}else{
$sp->addOffer($offer);
// echo 'added $offer '.$offer->getName()." with price : ".$offer->getPrice()."<br />";
}
if(sizeof($sp->getOffers()) > 0 ){
array_push($filteredResults,$sp);
}
}
}
the first time i change the $minPrice and $maxPrice variables the results are filtered right and exactly what i need
but after raising the $maxPrice again the high prices are not being added to the $filteredResults
i tried also to assign $offer and $result to new variables but still not working
any idea how to fix this ?
ps. i can't change the query or to fetch them already with the query.
When you save entities in the session this entities are serialized with the values that actual at the serialization moment. Next changes of entities are not affect the stored values if you don't rewrite them in the session.
Also entitiy serializing has some limitations on private properties.
I have to create a PHP web page with two text fields in which the user can enter minimum and maximum item prices from a SQL database. So I have items with prices. For example, if a user wants to see items between the prices 4 and 15, he can submit it and then it will show only the items in that price range. How can I do this? How to echo this?
Thank you!
I have this so far:
$min=$_POST["minimum"];
$max=&$_POST["maximum"];
$result = mysqli_query($con,"SELECT * FROM items WHERE selling price BETWEEN {$min}+1 AND {$max}");
Apart from a major SQL Injection issue, your script is looking fine. Just some small typs and syntax errors. Compare this one to yours:
$min=(int)$_POST["minimum"];
$max=(int)$_POST["maximum"];
$result = mysqli_query($con,"SELECT * FROM items WHERE selling_price BETWEEN {$min}+1 AND {$max}");
So, what did I change?
At least cast posted values to int to remove the chance of anyone injecting malicious SQL code into your query. You should use proper escaping in the future
You dont need to add the & character before in line two. You dont need to assign the value by reference. just assign the plain old way
column and table names can not conain spaces in MySQL. Are you sure that is the correct name of the column? Maybe there was an underscore?
One of the many safer and simpler ways of doing that would be
$dsn = "mysql:dbname=test;host=127.0.0.1";
$dbh = new PDO($dsn, 'username', 'password');
if(isset($_POST["minimum"]) && isset($_POST["maximum"]))
{
$min=floatval($_POST["minimum"]); //+1 is not needed
$max=floatval($_POST["maximum"]);
$sth = $dbh->prepare("SELECT * FROM items WHERE selling_price BETWEEN ? AND ?");
$sth->execute(array($min,$max));
while($row = $sth->fetch(PDO::FETCH_OBJ))
{
print_r($row);
}
}
That should do the trick for you:
if(isset($_POST['minimum'])){
$min = $_POST['minimum'];
}else{
$min = '';
}
if(isset($_POST['maximum'])){
$max = $_POST['maximum'];
}else{
$max = '';
}
$sql = "SELECT * FROM item WHERE selling_brice > '$min' AND selling_price < '$max'";
$query = mysqli_query($con, $sql);
$count = mysqli_num_rows($query);
if($query == true && $count > 0 ){
while ($row = mysqli_fetch_assoc($query)){
$price .= $row['selling_price'];
$price .= '<br />'
}
echo $price;
}else{
echo "NO results to Display";
}
Ofcourse this is not the best programing mysql injections, your query uses * etc....but this should work.
I am trying to make a script to check if an int is already added to my database. If so, it will re-generate another random number and check again. If it doesn't exist, it'll insert into the database.
However, I am having troubles. If a number exists, it just prints out num exists, how would I re-loop it to check for another and then insert that? I have tried to use continue;, return true; and so on... Anyway, here is my code; hopefully someone can help me!
<?php
require_once("./inc/config.php");
$mynum = 1; // Note I am purposely setting this to one, so it will always turn true so the do {} while will be initiated.
echo "attempts: ---- ";
$check = $db->query("SELECT * FROM test WHERE num = $mynum")or die($db->error);
if($check->num_rows >= 1) {
do {
$newnum = rand(1, 5);
$newcheck = $db->query("SELECT * FROM test WHERE num = $newnum")or die($db->error);
if($newcheck->num_rows >= 1) {
echo $newnum . " exists! \n";
} else {
$db->query("INSERT test (num) VALUES ('$newnum')")or die($db->error);
echo "$newnum - CAN INSERT#!#!#";
break;
}
} while(0);
}
?>
I think the logic you're looking for is basically this:
do {
$i = get_random_int();
} while(int_exists($i));
insert_into_db($i);
(It often helps to come up with some functions names to simplify things and understand what's really going on.)
Now just replace the pseudo functions with your code:
do {
$i = rand(1, 5);
$newcheck = $db->query("SELECT * FROM test WHERE num = $i")or die($db->error);
if ($newcheck->num_rows >= 1) {
$int_exists = true;
} else {
$int_exists = false;
}
} while($int_exists);
$db->query("INSERT test (num) VALUES ('$i')") or die($db->error);
Of course, you can do a little more tweaking, by shortening...
// ...
if ($newcheck->num_rows >= 1) {
$int_exists = true;
} else {
$int_exists = false;
}
} while($int_exists);
...to:
// ...
$int_exists = $newcheck->num_rows >= 1;
} while($int_exists);
(The result of the >= comparison is boolean, and as you can see, you can assign this value to a variable, too, which saves you 4 lines of code.)
Also, if you want to get further ahead, try to replace your database calls with actual, meaningful functions as I did in my first example.
This way, your code will become more readable, compact and reusable. And most important of all, this way you learn more about programming.
The logic is incorrect here. Your do-while loop will get executed only once (as it's an exit-controlled loop) and will stop on the next iteration as the while(0) condition is FALSE.
Try the following instead:
while($check->num_rows >= 1) {
$newnum = rand(1, 5);
$newcheck = $db->query("SELECT * FROM test WHERE num = $newnum")or die($db->error);
if ($newcheck->num_rows >= 1) {
echo $newnum . " exists! \n";
} else {
$db->query("INSERT test (num) VALUES ('$newnum')") or die($db->error);
echo "$newnum - CAN ISNERT#!#!#";
break;
}
}
Sidenote: As it currently stands, your query is vulnerable to SQL injection and could produce unexpected results. You should always escape user inputs. Have a look at this StackOverflow thread to learn how to prevent SQL injection.
Here is an example of some code that I threw together using some of my previously made scripts. You will notice a few changes compared to your code, but the concept should work just the same. Hope it helps.
In my example I would be pulling the database HOST,USER,PASSWORD and NAME from my included config file
require_once("./inc/config.php");
echo "attempts: ---- ";
$running = true;
while($running == true) {
//create random number from 1-5
$newnum = rand(1,5);
//connect to database
$mysqli = new mysqli(HOST, USER, PASSWORD, NAME);
//define our query
$sql = "SELECT * FROM `test` WHERE `num` = '".$$newnum."'";
//run our query
$check_res = mysqli_query($mysqli, $sql) or die(mysqli_error($mysqli));
//check results, if num_rows >= our number exists
if (mysqli_num_rows($check_res) >= 1){
echo $newnum . " exists! \n";
}
else { //our number does not yet exists in database
$sql = "INSERT INTO `test`(`num`) VALUES ('".$newnum."')";
$check_res = mysqli_query($mysqli, $sql) or die(mysqli_error($mysqli));
if ($check_res){
echo $newnum . " - CAN ISNERT#!#!#";
// close connection to datbase
mysqli_close($mysqli);
}
else{
echo "failed to enter into database";
// close connection to database
mysqli_close($mysqli);
}
break;
}
}
I would also like to note that this will continue to run if all the numbers have been used, you may want to put in something to track when all numbers have been used, and cause a break to jump out of the loop.
Hope this helps!
Code is below if I run one value in the array the results are correct if I run more than one value the results are of the price is incorrect its like it has messed around with the values somewhere ?? help appreciated
$dido=array('42204131','22204131');
foreach($dido as $did):
$query = "select * from dispatch,link where lid=dlid and did=$did";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
$vanc1=$row['vanc1'];
$vanc2=$row['vanc2'];
$vanc3=$row['vanc3'];
$vanc4=$row['vanc4'];
$vanc5=$row['vanc5'];
$anc1=$row['anc1'];
$anc2=$row['anc2'];
$anc3=$row['anc3'];
$anc4=$row['anc4'];
$anc5=$row['anc5'];
// price anc1
$querypanc1 = "select pprice from products where pid=$anc1";
$resultpanc1 = mysql_query($querypanc1);
while($row = mysql_fetch_array($resultpanc1))
{
$priceanc1=$row[pprice];
$tpriceanc1=$vanc1*$priceanc1;
}
// price anc2
$querypanc2 = "select pprice from products where pid=$anc2";
$resultpanc2 = mysql_query($querypanc2);
while($row = mysql_fetch_array($resultpanc2))
{
$priceanc2=$row[pprice];
$tpriceanc2=$vanc2*$priceanc2;
}
// price anc3
$querypanc3 = "select pprice from products where pid=$anc3";
$resultpanc3 = mysql_query($querypanc3);
while($row = mysql_fetch_array($resultpanc3))
{
$priceanc3=$row[pprice];
$tpriceanc3=$vanc3*$priceanc3;
}
// price anc4
$querypanc4 = "select pprice from products where pid=$anc4";
$resultpanc4 = mysql_query($querypanc4);
while($row = mysql_fetch_array($resultpanc4))
{
$priceanc4=$row[pprice];
$tpriceanc4=$vanc4*$priceanc4;
}
// price anc5
$querypanc5 = "select pprice from products where pid=$anc5";
$resultpanc5 = mysql_query($querypanc5);
while($row = mysql_fetch_array($resultpanc5))
{
$priceanc5=$row[pprice];
$tpriceanc5=$vanc5*$priceanc5;
}
$gtprice=$tpriceanc1+$tpriceanc2+$tpriceanc3+$tpriceanc4+$tpriceanc5;
$qrygt="UPDATE dispatch SET gtprice=$gtprice WHERE did=$did";
$resultgt=#mysql_query($qrygt);
}
endforeach;
1) The only possible issue I could spot in your code, is that when some of your select pprice from products where pid ... queries do not return any data, you retain value of $tpriceancX from previous iteration.
2) Also (out of topic) you can replace your 5 blocks of repeated code with for loop.
$gtprice = 0;
for ($i = 1; $i <= 5; $i++)
{
$querypanc = "select pprice from products where pid=".$row["anc$i"];
$resultpanc = mysql_query($querypanc);
while($pancrow = mysql_fetch_array($resultpanc))
{
$priceanc=$pancrow[pprice];
$tpriceanc=$row["vanc$i"]*$priceanc;
$gtprice += $tpriceanc;
}
}
Your first and biggest problem is the copy-pasta nature of your code. Let's try and break down what you're doing:
Setting up a list of ids
Running a query on those ids
Putting the results into an array
Running a separate query on each of those results
You are also using some very janky syntax. (ie foreach($foo as $bar):).
Break these things down into methods. What is a method? It takes an input and transforms it into an output.
//returns an array of price information
public function getPrices($idArray) { //note the good method and parameter names!
//do stuff
}
Now that we know what we are doing, we can start to fill in the implementation details:
public function getPrices($idArray) {
foreach($idArray as $id) {
//somehow get the gross-scale information
//then put it in a data object
//then call a function to get specific information
}
}
What should that sub-method do? Lets look at your current code snippet:
// price anc1
$querypanc1 = "select pprice from products where pid=$anc1";//sets up sql query
$resultpanc1 = mysql_query($querypanc1); //runs the query
while($row = mysql_fetch_array($resultpanc1)) { //for each result
$priceanc1=$row[pprice]; //gets the price
$tpriceanc1=$vanc1*$priceanc1; //calculates some other price
}
Those last two lines really suggest an object but maybe that's too heavyweight for your purpose. The first two lines are boiler plate you repeat endlessly. Lets write a function!
public function getPrices($name, $pid, $multiplier) {
$sqlQuery = "SELECT pprice FROM products WHERE pid=$pid";
$result = mysql_query($sqlQuery);
$prices = array();
while ($row = mysql_fetch_array($result) {
$key = "price".$name;//$key will be something like 'priceanc1'
$prices[$key] = $row[pprice];
$tkey = "tprice".$name;
$prices[$tkey] = $prices[$key] * $multiplier;
}
}
Now, this function is a bit unclean because it tries to do two things at once (queries the database and then massages the data into a usable array) but I wanted it to resemble what you were doing. With this function written we can go back to our higher level function an call it:
public function getPrices($idArray) {
foreach($idArray as $id) {
$sqlQuery = "SELECT * from dispatch, link WHERE lid=dlid and did=$id";
$prices = array();
while ($row = mysql_fetch_array($result) {
for ($idx = 1; $idx <= 5; $idx++) {
$name = "anc".$idx;
$pid = $row[$name];
$multiplier = $row["vanc".$idx];
$priceArray = getPrices($name, $pid, $multiplier);
$prices = array_merge($prices, $priceArray);
}
}
}
//put a var_dump here to check to see if you're getting good results!
return $prices;//Should be the aggregated prices you've gotten from the db
}
Now, that is what you're attempting to do, but I admit I don't understand how your database is set up or what your variables actually mean. Pressing on! We also note that unnecessary massaging of data falls away.
You can call this like so:
$ids = array();
$ids[] = 42204131;
$ids[] = 22204131;
$prices = getPrices($ids);
var_dump($prices);//shows the result of your work
Now that you have the prices, you can pass them to another function to run the update:
updatePrices($prices);
I'll let you write that part on your own. But remember; break down what you're doing and have repeated elements be handled by the same function. The real lesson to learn here is that programming is really communicating: your code doesn't communicate anything because there is so much repeated noise. Use good variable names. Tighten what you're doing down to functions with single tasks. This way anyone reading your code (including you!) will know what you're trying to do and where you've gone wrong.
i am trying to display data based on wether data in a field is new. instead of showing only the data that is new it is showing all data. can someone point out my error. many thanks
<?php
include("../../js/JSON.php");
$json = new Services_JSON();
// Connect to MySQL database
mysql_connect('localhost', 'root', '');
mysql_select_db(sample);
$page = 1; // The current page
$sortname = 'id'; // Sort column
$sortorder = 'asc'; // Sort order
$qtype = ''; // Search column
$query = ''; // Search string
$new = 1;
// Get posted data
if (isset($_POST['page'])) {
$page = mysql_real_escape_string($_POST['page']);
}
if (isset($_POST['sortname'])) {
$sortname = mysql_real_escape_string($_POST['sortname']);
}
if (isset($_POST['sortorder'])) {
$sortorder = mysql_real_escape_string($_POST['sortorder']);
}
if (isset($_POST['qtype'])) {
$qtype = mysql_real_escape_string($_POST['qtype']);
}
if (isset($_POST['query'])) {
$query = mysql_real_escape_string($_POST['query']);
}
if (isset($_POST['rp'])) {
$rp = mysql_real_escape_string($_POST['rp']);
}
// Setup sort and search SQL using posted data
$sortSql = "order by $sortname $sortorder";
$searchSql = ($qtype != '' && $query != '') ? "where ".$qtype." LIKE '%".$query."%' AND new = 1" : '';
// Get total count of records
$sql = "select count(*)
from act
$searchSql";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
$total = $row[0];
// Setup paging SQL
$pageStart = ($page -1)*$rp;
$limitSql = "limit $pageStart, $rp";
// Return JSON data
$data = array();
$data['page'] = $page;
$data['total'] = $total;
$data['rows'] = array();
$sql = "select *
from act
$searchSql
$sortSql
$limitSql";
$results = mysql_query($sql);
while ($row = mysql_fetch_assoc($results)) {
$data['rows'][] = array(
'id' => $row['id'],
'cell' => array($row['id'], $row['slot'], $row['service'], $row['activity'], $row['department'], $row['company'], $row['address'], $row['user'], $row['item'], $row['filebox'], date('d/m/Y',strtotime($row['date'])), $row['quantity'], $row['type'], $row['new'])
);
}
echo $json->encode($data);
?>
You should debug SQL by looking at the SQL query, not at the PHP code that produces the SQL query. If you echo $sql and look at it, you'll probably see any syntax errors much more easily.
You can also copy & paste that SQL and try to execute it in the MySQL command tool, and see what happens, whether it gives the result you want, you can profile it or use EXPLAIN, etc.
You're using mysql_real_escape_string() for integers, column names, and SQL keywords (ASC, DESC). That escape function is for escaping only string literals or date literals. It's useless for escaping unquoted integers, column names, SQL keywords, or any other SQL syntax.
For integers, use (int) to typecast inputs to an integer.
For column names or SQL keywords, use a whitelist map -- see example in my presentation http://www.slideshare.net/billkarwin/sql-injection-myths-and-fallacies
You're not testing for error statuses returned by any of your functions. Most functions in ext/mysql return false if some error occurs. You should check for that after every call to a mysql function, and report errors if they occur.
You're selecting a database using a constant name sample instead of a quoted string "sample". This might be intentional on your part, I'm just noting it.
Also, this is not related to your errors, but you should really upgrade to PHP 5. PHP 4 has been end-of-lifed for over two years now.
after looking at the code again and all the suggestions i think i should be using an AND clause and not WHERE. for example the code
$searchSql = ($qtype != '' && $query != '') ? "where ".$qtype." LIKE '%".$query."%' AND new = 1" : '';
this is the WHERE clause? which basically translates to:
$sql = "select *
from act
$searchSql
$sortSql
$limitSql"; <- original code
$sql = "select *
from act
WHERE company LIKE '%demo%' AND new = 1
$sortSql
$limitSql";<-updated code
am i on the right track?