简体   繁体   中英

How do I properly check to see if similar data is in database before inserting it, using a foreach loop

I would like to see if my "invoice_id" variable is already in the database before inserting it again. I would like for the foreach statement to loop through results, and issue out a statement if the invoice Id is already in the database.

 <?php require("connect.php"); $invoice=$_REQUEST['invoice_id']; $sql="SELECT * FROM invoices WHERE id='$invoice'"; $query=mysqli_query($conn,$sql) or die ("nope"); $row=mysqli_fetch_array($query); if(isset($row['id'])){ $sql3="SELECT * FROM transactions"; $query3=mysqli_query($conn,$sql3); $row3=mysqli_fetch_array($query3); foreach($row3['invoice_id'] as $value){ if($value==$invoice){ echo "That invoice has already been paid"; } } $invoice_id=$row['id']; $mcode=$row['mcode']; $rcode1=$row['rcode1']; $rcode2=$row['rcode2']; $date=date('Ym-d'); $sql2="INSERT INTO transactions(id,invoice_id,mcode,rcode1,rcode2,date) VALUES('','$invoice_id','$mcode','$rcode1','$rcode2','$date')"; $query2=mysqli_query($conn,$sql2) or die ("No Connect"); echo "Invoice has been paid!"; } ?> 

Okay, this is your first problem.

$invoice = $_REQUEST['invoice_id'];
$sql = "SELECT * FROM invoices WHERE id='$invoice'";

https://secure.php.net/manual/en/security.database.sql-injection.php

It's peripheral to your question so I feel no guilt about just posting a link, but please, for the love of God, read this and understand it. The code you posted has a security hole a mile wide in it. That's especially concerning since you're apparently dealing with financial data...

In your case, I could send a request to your page with myfile.php?invoice_id=%27%20OR%20%27%27%3D%27 which decodes as ' OR ''=' . Your code would happily sub in my "invoice ID", resulting in the following query:

SELECT * FROM invoices WHERE id='' OR ''=''

Since '' always equals '' , your application would then return every invoice in the database.

Now, on topic. I assume you're doing more in your code than checking for paid/not paid, and the rest of the invoice data is relevant. In that case, you want to use a join:

// Sanitizing can be as simple as casting to int, although in most cases
// you'd use something like mysqli_escape_string() instead.
$invoice_id = (int) $_REQUEST['invoice_id'];

// LEFT JOIN will make all fields in t[ransactions] available to the query.
//
// If no records in the transactions table satisfy the
// t.invoice_id = i[nvoice].id condition, then all transactions fields will
// be null. So that `t.id IS NOT NULL` will be 1 (true) if there is a
// corresponding transaction, or 0 (false) if there isn't.
//
// You can also add additional conditions to the join, for instance if
// you need to check the transaction status:
// LEFT JOIN transactions AS t ON (t.invoice_id = i.id AND t.status = 'paid')
$sql = "
    SELECT i.*, (t.id IS NOT NULL) AS is_paid FROM invoices AS i
    LEFT JOIN transactions AS t ON t.invoice_id = i.id
    WHERE i.id = $invoice_id
";

$res = mysqli_query($conn, $sql);
if (empty($res) || !$res->num_rows) {
    die('not found');
}

$invoice = $res->fetch_object();

if ($invoice->is_paid) {
    echo "Invoice {$invoice->id} has been paid!";
} else {
    echo "Invoice {$invoice->id} has not been paid!";
}

If you only wanted to check if an invoice had been paid, you could just query the transactions table directly:

SELECT * FROM transactions WHERE invoice_id = 123

Further reading:

https://dev.mysql.com/doc/refman/5.6/en/join.html

https://en.wikipedia.org/wiki/SQL_injection (again)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM