I hvae the following PHP source:
$type_ID =$_GET["typeID"];
try{
$article_ID =$_GET["articleID"];
$select_query = mysql_query("SELECT articleContent, articleTitle From articles WHERE articleID=$article_ID && typeID=$type_ID");
}
catch(Exception $e)
{ $select_query = mysql_query("SELECT articleContent, articleTitle From articles WHERE typeID=$type_ID");
}
$row = mysql_fetch_assoc($select_query);
echo '<h1>'.$row['articleTitle'].'</h1>';
echo $row['articleContent'];
I know that this code is no safe, and yo can easlily do sql injection.
There problem here is that it's didn't go into the catch part (after the try)even when it should.
The solution may be easy but I can't solve it.
Why it's didn't go into the catch section?
You'd have to change your queries to use the or to catch the fail in this case something like this may work though I'm not 100% (can anyone correct me?) You'd be far better off moving away from mysql_ functions though and moving to mysqli or pdo in an OO style then you can better trap and handle the errors.
$type_ID =$_GET["typeID"];
try{
$article_ID =$_GET["articleID"];
$select_query = mysql_query("SELECT articleContent, articleTitle From articles WHERE articleID=$article_ID && typeID=$type_ID") or throw new Exception("ERROR HERE");
}
catch(Exception $e)
{
$select_query = mysql_query("SELECT articleContent, articleTitle From articles WHERE typeID=$type_ID"); // note we can't throw exception here because its already in the try catch. perhaps we should look at something like the finally statement.
//echo $e->getMessage(); //uncomment this line if you want to output the exception error text set above
}
$row = mysql_fetch_assoc($select_query);
echo '<h1>'.$row['articleTitle'].'</h1>';
echo $row['articleContent'];
Actually just had a thought you'd be much better doing something like this and validating your inputs before hand. (note i'm doing no string escaping here don't forget to do it)
$type_ID =$_GET["typeID"];
$article_ID =$_GET["articleID"];
if (strlen($type_ID)>0 && strlen($article_ID)>0 && is_numeric($type_ID) && is_numeric($article_ID)) {
$sqlquery = "SELECT articleContent, articleTitle From articles WHERE articleID=$article_ID && typeID=$type_ID";
} else {
$sqlquery = "SELECT articleContent, articleTitle From articles WHERE typeID=$type_ID";
}
try {
$queryresult = mysql_query($sqlquery) or throw new Exception("Query Failed");
} catch(Exception $e) {
echo $e->getMessage();
}
So basically you're validating and checking your inputs and switching your sql statements before then your try catch logic is purely for did the query succeed or fail which is far more sensible than what you were attempting.
Mysql query will return FALSE on error
So you can throw an exception for that
$result = mysql_query("SELECT articleContent, articleTitle From articles WHERE articleID=$article_ID && typeID=$type_ID");
if(!$result) throw new Exception("Invalid query: ". mysql_error());
And catch them in your catch block
catch(Exception $e)
{ echo $e->getMessage()}
Its up to you what you will do with it echo or log.
Related
Here is my script:
$id = $_GET['id'];
$value = $_GET['val'];
// database connection here
try{
$db_conn->beginTransaction(); // this
$stm1 = $db_conn->prepare("UPDATE table1 SET col = "updated" WHERE id = ?");
$stm1->execute(array($value));
$done = $stm->rowCount();
if ($done){
try {
$stm2 = $db_conn->prepare("INSERT into table2 (col) VALUES (?)");
$stm2->execute(array($id));
} catch(PDOException $e){
if ((int) $e->getCode() === 23000) { // row is duplicate
$stm3 = $db_conn->prepare("DELETE FROM table2 WHERE col = ?");
$stm3->execute(array($id));
}
}
} else {
$error = true;
}
$db_conn->commit(); // this
}
catch(PDOException $e){
$db_conn->rollBack();
}
First of all, I have to say, my script works. I mean the result or it is as expected in tests. Just one thing scares me. I read the documention and seen this sentence:
Won't work and is dangerous since you could close your transaction too early with the nested commit().
I'm not sure what's the meaning of sentence above, just I understand maybe I shouldn't use nested try - catch between beginTransaction() and commit(). Well I got it right? doing that is dangerous?
Exceptions have no direct relation to transactions. You can add as many catch blocks in your code as you need.
So your code is all right, given you already set PDO error reporting to Exceptions.
My goal is to use a transaction and a prepared statement simultaneously, to achieve both integrity of data, and prevention of SQL injection.
I have this:
try {
$cnx = new PDO($dsn,$dbuser,$dbpass);
$cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$cnx->beginTransaction();
$cnx->query("SELECT * FROM users WHERE username=$escaped_input");
$cnx->query("SELECT * FROM othertable WHERE some_column=$escaped_input_2");
$cnx->commit();
}
catch (Exception $e){
$cxn->rollback();
echo "an error has occured";
}
I would like to incorporate the query as one would with a prepared statement:
$stmt=$cxn->prepare("SELECT * FROM users WHERE username=?");
$stmt->execute(array($user_input));
$stmt_2=$cxn->prepare("SELECT * FROM othertable WHERE some_column=?");
$stmt_2->execute(array($user_input_2));
How can I achieve that?
Edit
I get this error:
PHP Parse error: syntax error, unexpected T_CATCH
Here is my updated code:
try
{
$cnx = new PDO($dsn,$dbuser,$dbpass);
$cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$cnx->beginTransaction();
$stmt=$cnx->prepare("SELECT * FROM users WHERE username=?");
$stmt->execute(array($username));
$cnx->commit();
while ($row=$stmt->fetch(PDO::FETCH_OBJ)){
echo $stmt->userid;
}
catch(Exception $e) {
if (isset($cnx))
$cnx->rollback();
echo "Error: " . $e;
}
Just call "execute" after you call "beginTransaction".
Where you call "prepare" doesn't really matter.
Here's a complete example:
http://php.net/manual/en/pdo.begintransaction.php
EXAMPLE:
try {
$cnx = new PDO($dsn,$dbuser,$dbpass);
$cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$cnx->beginTransaction();
$stmt=$cxn->prepare("SELECT * FROM users WHERE username=?");
$stmt->execute(array($user_input));
$stmt_2=$cxn->prepare("SELECT * FROM othertable WHERE some_column=?");
$stmt_2->execute(array($user_input_2));
$cnx->commit();
}
catch (Exception $e){
$cxn->rollback();
echo "an error has occurred";
}
PS:
1) I'm assuming, of course, that $user_input and $user_input_2 are available immediately. You don't want your transaction hanging open unnecessarily long ;)
2) Based on your comment reply above, I think you might be confusing "execute" and "begin tran/commit". Please look at my link.
3) Do you even need a transaction? You're just doing two "select's".
4) Finally, why not do one "join" (or union, if compatible) instead of two "select's"?
try
{
$cnx = new PDO ($dsn,$dbuser,$dbpass);
$cnx->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$cnx->beginTransaction ();
$stmt = $cnx->prepare ("SELECT * FROM users WHERE username=?");
$stmt->execute(array($username));
$cnx->commit();
while ($row = $stmt->fetch (PDO::FETCH_OBJ)){
echo $row->userid;
}
}
catch (Exception $e) {
if (isset ($cnx))
$cnx->rollback ();
echo "Error: " . $e;
}
}
Did you mean this?
try {
$cnx = new PDO($dsn,$dbuser,$dbpass);
$cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$cnx->beginTransaction();
$stmt=$cnx->prepare("
SELECT * FROM users, othertable
WHERE users.username=?
AND othertable.some_column=?");
$stmt->execute(array($user_input,$user_input_2));
$cnx->commit();
}
catch (Exception $e){
$cnx->rollback();
echo "an error has occured";
}
That is assuming that the two tables data does not have duplicate field names, otherwise you're going to have to use:
SELECT users.field1 as u_field1, othertable.field1 as o_field1 FROM users, othertable
WHERE users.username=?
AND othertable.some_column=?
I'm converting my mysql_query() calls to PDO but don't understand how to get a false result on failure. This is my code:
$STH = $DBH->query("SELECT * FROM articles ORDER BY category");
$STH->setFetchMode(PDO::FETCH_ASSOC);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
This is what I'm trying to do but does not work:
if($STH==false) {
foreach($dbh->errorInfo() as $error) {
echo $error.'<br />';
}
}
When using PDO the nature of querying usually goes down like so:
try
{
$STH = $DBH->prepare("SELECT * FROM articles ORDER BY category"); //Notice the prepare
$STH->setFetchMode(PDO::FETCH_ASSOC);
//No need to silent as the errors are catched.
if($STH === false) //Notice the explicit check with !==
{
//Do not run a foreach as its not multi-dimensional array
$Error = $DBH->errorInfo();
throw new Exception($Error[2]); //Driver Specific Error
}
}catch(Exception $e)
{
//An error accured of some nature, use $e->getMessage();
}
you should read errorInfo very carefully and study the examples.
Can somebody help me in converting the following code written using if-else to try/catch. Also let me know is trycatch needed in this case or if-else is apt
$results = mysql_query($query);
if(mysql_num_rows($results)!=0)
{
while(($result = mysql_fetch_row($results))!=FALSE)
{
$res ="DELETE FROM table1 WHERE id ='".$result['id']."'";
if(mysql_query($res)==false)
{
echo mysql_error();
exit;
}
}
echo $res ="DELETE FROM table2 WHERE id ='".$id."'";
if(mysql_query($res)!==false)
{
header("Location:list.php?m=4");
}
else
{
echo mysql_error();
exit;
}
}
else
{
echo "Error";
}
try...catch only makes any sense if your functions are throwing exceptions. If they don't, there's nothing to catch. I'd start with this as a refactoring:
$results = mysql_query($query);
if (!mysql_num_rows($results)) {
echo 'No results!';
exit;
}
$ids = array();
while (($result = mysql_fetch_row($results)) !== false) {
$ids[] = $result['id'];
}
$ids = array_map('mysql_real_escape_string', $ids);
$query = "DELETE FROM table1 WHERE id IN ('" . join("','", $ids) . "')";
if (!mysql_query($query)) {
echo mysql_error();
exit;
}
$query = "DELETE FROM table2 WHERE id = '$id'";
if (!mysql_query($query)) {
echo mysql_error();
exit;
}
header("Location: list.php?m=4");
exit;
This can still be improved a lot, but it's already an improvement over your spaghetti logic. If you're seriously interested in properly using exceptions, you should first move on to properly using functions for repetitive tasks (like the error, exit parts), then possibly restructure the whole thing into classes and objects, and lastly use exceptions to communicate between the now nested layers. Maybe start using a PHP framework to get a feeling for the whole thing.
Putting exceptions into the above code would be hardly more than a goto, but just for illustrative purposes:
try {
$results = mysql_query($query);
if (!mysql_num_rows($results)) {
throw new Exception('No results!');
}
$ids = array();
while (($result = mysql_fetch_row($results)) !== false) {
$ids[] = $result['id'];
}
$ids = array_map('mysql_real_escape_string', $ids);
$query = "DELETE FROM table1 WHERE id IN ('" . join("','", $ids) . "')";
if (!mysql_query($query)) {
throw new Exception(mysql_error());
}
$query = "DELETE FROM table2 WHERE id = '$id'";
if (!mysql_query($query)) {
throw new Exception(mysql_error());
}
header("Location: list.php?m=4");
exit;
} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
exit;
}
from the sound of it, it seems you think try/catch and if-else as the same behaviour. That is not the case. Try catch is used to prevent an exception from making the application crash or to handle exceptions gracefully, and to perform logging and giving user feedback. If-else (else if) is used to check the internal state of your application, and perform different actions accordingly.
Generally, a try-catch is less efficient than if there is a switch-case or else-if approach to the problem.
function get_total_adults()
{
$sql = "SELECT SUM(number_adults_attending) as number_of_adults FROM is_nfo_rsvp";
$result = mysql_query($sql) or die(mysql_error());
$array = mysql_fetch_assoc($result);
return $array['number_of_adults'];
}
I know there is a way to write this with less code. I'm just looking for the best way (without using something like ezSQL).
function get_total_adults() {
$sql = 'SELECT SUM(number_adults_attending) FROM is_nfo_rsvp';
$result = mysql_query($sql) or die(mysql_error());
// I'd throw a catchable exception (see below) rather than die with a MySQl error
return mysql_result($result, 0);
}
As to how I'd rather handle errors:
function get_total_adults() {
$sql = 'SELECT SUM(number_adults_attending) FROM is_nfo_rsvp';
$result = mysql_query($sql);
if (!$result) {
throw new Exception('Failed to get total number of adults attending');
}
return mysql_result($result, 0);
}
try {
$total_adults = get_total_adults();
} catch(Exception $ex) {
die('Whoops! An error occurred: ' . $ex->getMessage());
// or even better, add to your template and dump the template at this point
}
// continue code
You can drop the "as number_of_adults" part of the query and use mysql_result.
You could also try refactormycode.com