PHP prevent die before executing full code - php

I have code as below where I am redirecting the user at the end but sometimes it seems that the output variable is not getting set or insert query is not getting executed . So is there any way I can wait for all the operations to be completed before the die statement is executed.
Thanks
$diff=levenshtein(strtolower($str1),strtolower($str2));
if($diff<=2)
{
$output="ok";
}
else
{
$output="Not ok";
}
$query="INSERT INTO `table` (`sn`, `output`) VALUES (NULL,'$output')";
$result=mysqli_query($con,$query);
header('Location: http://www.domain.com/');
die;

There may be several reasons why it doesn't work.
The first one and most obvious is that is enough to have only one simple warning on your page (variable X is not set) and this will broke your header() command. It would say that headers have been already set.
The second problem is that sometimes the server is so busy answering other request and your $con variable will be a Boolean false instead of a reliable database connector, therefore your query could fail because of this too.
I encountered both situations in real life and I solved them by ensuring that every variable is set before use it and by checking if the query was executed successfully.
You can check if a variable is set by using this code:
if (!isset($variable)) $variable = "set me here";
You can check if your query was succesfully executed by adding this:
if (!$result) {
//do something here in case your query failed
}

Related

Does error handling on every query affects performance?

Hello i'm wondering if putting error handler in every query especially Inserts and Updates affects the performance of web application with huge database? if not how can i use try catch properly on every query to stop the process and inform the user? is it possible to rollback inserted data?
sample error logging:
$query = mysqli_query($conn, "insert into `table`(`fields`) values('$variable')");
if(!$query){
write_mysql_log("logs here", $conn);
echo "<script>alert('Error message, like something went wrong'); window.location = 'page.php';</script>";
}
No. You should be checking for errors from the query.
The check for errors is entirely separate from running the query itself. The query will still return errors, even if you don't check for them.

How to stop PHP and SQL execution when user disconnects?

I have a quite heavy SQL search query that takes a few minutes to complete, called from a PHP script that's called by an ajax request.
Problem is, users often click the search button many times from impatience, and each time it creates a new ajax request, and a new PHP script execution. But the old ones continue executing, even though the connection has been dropped. This causes the SQL server load to constantly be at 100% CPU usage.
So I tested my theory that script execution continues even after the browser tab is closed. I used 2 types of queries, an ad hoc query and a stored procedure execution, both methods do the same thing, inserting the numbers 1-9 into a table, with a 2 second delay between each number.
Ad hoc query:
for($i = 1; $i < 10; $i++){
$sql = "INSERT INTO t (i) VALUES(?)";
$res = pdoQuery($sql, array($i));
if($res === false){
echo $pdo->getErrorMessage();
http_response_code(500);
exit();
}
sleep(2);
}
SP call:
$sql = "EXEC sp_Slow";
$res = pdoQuery($sql);
if($res === false){
echo $pdo->getErrorMessage();
http_response_code(500);
exit();
}
How I tested: using buttons that trigger ajax calls to each script, I tested them, by clicking the button and immediately closing the tab. And then monitoring the data in the table. And just as I suspected, new data gets inserted every 2 seconds. (This also happens if I directly open the script in the browser and closing the tab, instead of requesting it through ajax)
I need a way to completely kill both PHP and SQL execution whenever the user disconnects, transactions are not important because it's just a select operation.
You can change this behaviour using php.ini directive or at runtime with ignore_user_abort() function.
Here's what I did, from the comment by #Robbie Toyota, thanks!
if(!empty($_SESSION['SearchSPID'])){
$sql = "KILL " . $_SESSION['SearchSPID'];
$res = pdoQuery($sql);
if($res === false){
exit('Query error: failed to kill existing spid:' . $_SESSION['SearchSPID']);
}
$_SESSION['SearchSPID'] = null;
}
$sql = "SELECT ##spid AS SPID";
$res = pdoQuery($sql);
$spid = $res->row_assoc()['SPID'];
$_SESSION['SearchSPID'] = $spid;
// do long query here
$_SESSION['SearchSPID'] = null;
Of course using this method you have to be careful about session file locking, which if happens will make this whole thing pointless, because then the requests will be sequential and not parallel

MySql Trigger when attempting to insert into the same table and selecting the last record of the same data

I have a table T1 and firing a trigger after insert on T1 and calling external PHP programm using UDF where the app is looking for a last inserted data and do a action on condition base but it is not working as expected.. Please help as I guess that we cannot select the data from the same table where we are firing a trigger?? Is it so?
TRIGGER
DELIMITER ##
CREATE TRIGGER CALL
AFTER INSERT ON call_test
FOR EACH ROW
BEGIN
DECLARE cmd CHAR(255);
DECLARE result int(10);
SET cmd=CONCAT('php /var/www/html/test/call.php');
SET result = sys_exec(cmd);
END;
##
DELIMITER ;
call.php
function connect_db() {
$db_connection = mysql_connect("localhost","root","test") or die (mysql_error());
$db_select = mysql_select_db('testdb') or die (mysql_error());
}
connect_db();
$sql2=mysql_query("SELECT * FROM call_test ORDER BY createtime desc limit 1") or die(mysql_error());
$res = mysql_fetch_array($sql2);
if(strstr($res['name'],'go')!=false)
{
echo "inserted";
//sleep(10);
$sql4=mysql_query("insert into call_test_auto (name,createtime) values ('from UDF automatic2','".$today."')") or die(mysql_error());
}
else
{
echo "not inserted";
}
yes you can Sam. It is in row aliased by NEW. See Trigger Syntax and Examples
Your task is to do whatever is necessary to get things into variables so that you can concat and call your UDF with them as command line parameters. As seen here, where that gentleman sent a command line argument of Sarbajit to his C program he had compiled.
In your case, you are just calling PHP and nothing is happening!
Enabling sys_exec
It is not as if your average Joe is likely to even going to survive the call to sys_exec() without receiving a Syntax Error. See This Question on the Stack and the link for github at top of that question.
Things Failing silently
Remember that mysql Triggers and Events (as in Create Event) run and succeed to your wishes or don't, but do so silently. You might not even know that the above Syntax Error occurred. That would not be the case for a Stored Procedure run by a user in a query that had error reporting.
Of course, a Trigger or Event could call a Stored Procedure, but there is no UX to that, so sys_exec() syntax errors would go unnoticed.

displaying errors if mysql_query not successful

I created a debug function to email me the mysql error and query executed if a query is not successful.
I call it like this:
mysql_query($sql) or $this->debug->dbErrors($sql);
And the function is:
function dbErrors($sql = ''){
if($this->doDebug)
echo mysql_error()."<br/>".$sql;
else
#mail(hidden_email,$_SERVER['HTTP_HOST'].' Mysql Error','A error occured in '.$_SERVER['HTTP_HOST'].':<br/>'.mysql_error().'<br/>'.$sql);
}
The problem is that i'm receiving emails even when the query executes fine (at least the data is inserted and everything works out ok)
What i doing anything wrong?
Thanks
That 'or' construct may be causing issue, I would do something like:
$result = mysql_query($sql);
if (!$result) {
$this->debug->dbErrors($sql);
}
This way you are doing an explicit check to see if $result is a boolean false (query is invalid), or a resource (query is valid). The point is to only call on $this->debug->dbErrors() if there indeed is an issue, otherwise the way your code is written, every query will be emailed.
or something simple like:
mysql_query($sql) or die(dbErrors($sql));

mysqli never returns anything

As part of a PHP web application, I'm querying a MySQL database using mysqli and prepared statements.
I've used exactly the same code on a few queries and it works, but on one particular query, it always returns an empty record set. I've run exactly the same query from the MySQL command line, and it correctly returns the result. I've checked the parameters being passed in, and they're fine.
I've spent the best part of a day trying to figure out why I'm always getting an empty record set with no errors or warnings. I've got PHP's errors set to display on the page, and I've got them set to E_ALL|E_STRICT. I still don't get any warnings or errors.
I've tried all the obvious things, like making sure I can actually connect to the database, checking the parameters that are being passed in, and making sure the row I'm trying to return actually exists in the database. I've had var_dump()s and die()s all over the page to check what's coming back, and it's always a legitimate, but empty, recordset.
function salt() {
return("I've removed my salt from this sample code");
}
function openDatabase() {
$conn = new mysqli("127.0.0.1", "username", "password", "database")
or die("Error: Could not connect to database.");
return($conn);
}
function checkUserCredentials($username, $password) {
$goodPassword = md5(salt().$username.$password);
$conn = openDatabase();
$query = $conn->stmt_init();
$query->prepare("SELECT id FROM users WHERE email = ? AND passwordHash = ?")
or die('Problem with query');
$query->bind_param("ss", $username, $goodPassword)
or die('Error binding parameters');
$query->execute() or die("Could not execute");
$query->bind_result($col1) or die ("Could not bind result");
if ($col1 !== 0) {
die("Authentication Complete");
} else {
die("Authentication Failure! Number of Rows: ".$query->num_rows." Username: " . $username . " Password Hash: " . $goodPassword);
}
}
Any feedback is appreciated. I'm sure I'm missing something simple, but if I didn't shave my head I'd be tearing my hair out right now.
Thanks
I'm not familiar with the mysqli library (I usually use PDO which provides a very similar cross platform API) so I can't immediately see any problem. However, you might try watching the mysqld log. See here for info:
http://dev.mysql.com/doc/refman/5.1/en/query-log.html
By tailing the log, you should be able to see the exact query that was submitted.
One final note, I notice you're using a fixed salt value. Wouldn't it be better to generate this value randomly each time you need it and then store it in the users table? Generally, a salt is not intended to be secret, it's just there to prevent people precomputing tables of passwords using the hash algorithm that you use.
In case anyone else runs into similar issues, it really helps if you run fetch() on your mysqli_stmt object.
In my code above, the solution looks like this:
$query->bind_result($col1) or die ("Could not bind result");
$query->fetch(); // <--- How could I forget to do this?
if ($col1 !== 0) {
return true;
} else {
return false;
}
Added on behalf of OP

Categories