PDO error handling [duplicate] - pdo

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 5 years ago.
From a tutorial on the intertubes I learned a bit about doing PDO queries. The tutorial used try/catch and the queries are basically structured like so:
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $user, $pass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $dbh->prepare("UPDATE users yada yada yadda");
$stmt->bindParam(':param1', $param1, PDO::PARAM_INT);
$stmt->bindParam(':param2', $param2, PDO::PARAM_INT);
$stmt->execute();
}
catch(PDOException $e)
{
echo $e->getMessage();
}
This of course echos mysql errors on the screen. Not that I intend on having bad queries, but I do not like the idea of echoing out errors right on the screen, figuring what if an attacker tries to induce said errors and try to learn something from them.
Is there a better way to do this so that any errors go to a log file instead, or do I in actuality have nothing to fear in this regard since the bound parameters eliminate the risk of any sql injection?

The tutorial is correct in that you want to use try..catch blocks to catch code that will possibly cause an error and bring down whatever you're loading. So, if you have some code that is dependent on this code executing you'd want to include it in your try section. If you absolutely need this code to execute for whatever you're creating to work, then you'll probably want to catch the error and redirect the user to some type of error page.
If you use the php error log function then instead of
echo $e->getMessage();
You can use
error_log($e->getMessage(),0);
to send the error message from PDO directly to your php error log. If you don't know where the error log is, you can check out this link for a couple pointers to it if you're running a *nix system. If you're running windows there should be a config file somewhere that will tell you. Or you can check the php ini file for the location it's pointing to for a surefire way to find the log.

Is there a better way to do this
Yes, sure!
That's apparently wrong way of handling PDO errors this tutorial taught you.
So, just get rid of these try..catch commands - that's all.
This way you'll have PDO exceptions handled the same way as other PHP errors. Thus, in case of query error your script will be halted and error will be logged (if you tell PHP so).
To tell PHP so, you have to set log_errors ini directive to 1
To tell PHP not to show errors on-screen, set display_errors ini directive to 0 (on a development server you may wish to reverse them though)

Well, my answer probably not in the best practice, so please leave it to the last option. But for my case, it works perfectly.
PDO::__construct however will give you an exception anyway no matter what you set in PDO::ATTR_ERRMODE. I don't know why they design it to behave like that.
My way to solve this problem is to create a code area i call it Debug Critical Section (means you need very careful about the codes in the section), any errors in this section will not directly output to user.
Here is the code i made for my framework:
private function doPDOConnect($dbIndex, &$DBInfo, &$error) {
$dbh = null;
$successed = false;
if (!isset($this->connectedDB[$dbIndex])) {
// Enter Critical Section so no error below belowing code will cause error output, but the error still in log though
facula::core('debug')->criticalSection(true);
try {
$dbh = new PDO($DBInfo['Driver'] . ':' . $DBInfo['Connection'] . '=' . $DBInfo['Host'] . ';dbname=' . $DBInfo['Database'], $DBInfo['Username'], $DBInfo['Password'], array( PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_TIMEOUT => $DBInfo['Timeout'] )); // ATTR_ERRMODE => PDO::ERRMODE_WARNING. or we will cannot get anything even error happens
$dbh->facula_prefix = $DBInfo['Prefix'];
$dbh->facula_index = $dbIndex;
$dbh->facula_connection = $DBInfo; // In order you want to reconnect this specify database after connection lost etc, remove if you worry about the security issue.
$successed = true;
} catch (PDOException $e) {
$error = $e->getMessage(); // If any error, catch it, to &$error.
}
// Exit Critical Section, restore error caught
facula::core('debug')->criticalSection(false);
if ($successed) {
return $this->connectedDB[$dbIndex] = $dbh;
}
} else {
return $this->connectedDB[$dbIndex];
}
return false;
}
So in your case, you may replace my facula::core('debug')->criticalSection to display_errors off/on to handle the error display handler correctly.
For example:
$display_error_status = ini_get('display_errors');
function criticalSection($entered) {
global $display_error_status;
if ($entered) {
ini_set('display_errors', '0');
} else {
ini_set('display_errors', $display_error_status);
}
}

Related

Tcl: catch errors from all commands

Sorry, I couldn't come up with a better title. My problems is the following: If I execute a Tcl proc, I can wrap the execution in catch to catch and process errors. I do this in my code to have the same error output everywhere. However, my program provides numerous procs which the user can use in scripts (mostly at the outermost level), and it would be cumbersome if the user would have to wrap every one of them in a catch. I could of course use an additional level of indirection in each of those commands, but I wanted to ask whether there is a way to catch errors from all commands executed, without explicitly using catch on each invocation?
Thanks for your help!
Read this paragraph first: ↓
The single most important principle of error handling is don't throw away errors unless you know for sure that that's the correct way to handle them. Doing so just because they're unsightly is very bad! (Logging them is far better.)
The closest you can get is to run the whole of your existing code inside a catch or try. You can put a source inside that, so a little driver script to retrofit on existing code is just something like:
set argc [llength [set argv [lassign $argv argv0]]]
catch {source $argv0}
Assuming you're applying it during the call to the overall script. You also might need to set up interp bgerror:
interp bgerror {} {apply {{msg opt} {
if {[lindex [dict get $opt -errorcode] 0] eq "EXPECTED"} {
# Ignore this
} else {
# Unexpected error; better tell the user
puts "ERROR: $msg"
puts [dict get $opt -errorinfo]
}
}}}
It's not a really good idea to do this though. If you hide all the errors, how will you find and fix any errors? Using try is better, since that lets you hide only expected errors:
try {
source $argv0
} trap EXPECTED {} {
# Ignore this
}
and I'd probably wrap things up so that I have local variables:
apply {{} {
global argv0 argv argc
set argc [llength [set argv [lassign $argv argv0]]]
try {
uplevel #0 [list source $argv0]
} trap EXPECTED {msg} {
# Log this; the logging engine is out of scope for the question
log DEBUG $msg
}
}}
You'll need to experiment to see what to trap.

If condition inside Concrete5 Job not working

I don't even have a clue why this is happening. The if condition in my job is not working properly. I triple checked the $flag variable and it is true. Still the code always goes to the else condition.
$flag = file_exists($csvFile);
if($flag){
//A big chunk of code
} else {
return 'Whatever you do I will always go here XD';
}
I hard coded true inside if, it works properly. Then another if inside that chunk of code also always goes to else. Again double checked Express. Express object exists and object is returned properly. And is_object returns true.
$flag = file_exists($csvFile);
if(true){
//Some code here
$entity = Express::getObjectByHandle('user');
if(is_object($entity)){
// Another chunk of code
} else {
return 'You cant escape from me that easily... XD';
}
//some code here
} else {
return "Now I'm a good boy";
}
Tried a bunch of things. The code works without any problems in single page controllers. What ever I do it's just not working. I'm running PHP 5.6.10 on MAMP. Conceret5 8.1.0
The only time I've seen something like this is with a buggy older version of PHP.
You could try moving some code around like so:
if($flag = file_exists($csvFile)) {
// code to handle file
} else {
// no file
}
A followup post would help...
Well. Looks like I found the fix. It looks like a simple matter but don't know for sure. I was running the job from dashboard, I didn't knew I could run the same job from the url as well (Automate job option URL). It worked fine when I ran it from URL and Magically it started working inside the Dashboard as well. I will look into it in detail when I get the time.

How do i stop SSIS Script component to process data

i am processing a ragged semicolon delimited file using script component as transformation.
The component is able to process the data and load to oledb destination. But when error is found it should stop processing further. As i am using try catch block the component doesn't fail and continue to process till the end.
Is there any way i could stop the processing further without failing the component/package?
Let me know if any other information/details required?
sample code:
str.split(";");
if(column[0] == "H")
{
col1=Column[3];
}
if(column[0] != "T")
{
try
{
Row.col1=Column[0];
Row.col2=Column[1];
.....
}
catch
{
update the variable to check if we have error in file.
}
}
Thank you for your time.
The general idea will be that you want to use try/catch blocks to ensure the data processing itself doesn't abort. Once you know your script isn't reporting a failure back to the engine, it's a simple process to not call the AddRow()
Pseudocode
foreach(line in fileReader)
{
try
{
// perform dangerous operations here
// Only add row if you have been able to parse current line
Output0Buffer.AddRow();
Output0Buffer.Col1 = parsedContent;
}
catch
{
// Signal that we should break out of the loop
// do not propagate the error
// You might want to do something though so you know you
// have an incomplete load
break;
}
}
If you are looking to just skip the current bad line, you can substitute continue for the break above.
C# loop - break vs. continue
I didn't get any help from anywhere, But as a work around i have placed a return statement in the code. It checks the error variable if it's true then i will return without processing further. But the thing still is it processes the whole file :(. But it works!!!

JSLint error: Expected 'ignore' and instead saw 'ex'

I use JSLint all the time, but just today, I came across an error that I've never seen before. With the following code, I got the error shown below:
try {
document.execCommand('BackgroundImageCache', false, true);
} catch (ex) {}
Error:
Expected 'ignore' and instead saw 'ex'.
} catch (ex) {}
So I changed my code to the following, and the error went away:
try {
document.execCommand('BackgroundImageCache', false, true);
} catch (ignore) {}
I can't find any explanation on the Internet regarding why this would fix the error. Does anyone know what's up or why this fixed the problem?
Thank you.
I think you're right -- jslint didn't used to complain like this. Instead, it told you that you needed to do something with ex, right? I'll check github to see and edit this later. EDIT: Great catch [by you]! Crockford, JSLint's author, added this on April 29th of this year around line 3444. And he uses empty catch blocks in jslint's source, so I guess he has to give us the kludge too. ;^)
JSLint wants you to kludge empty catch blocks with ignore as the variable name so that it's obvious to people reading your code that you intentionally meant not to do anything in your catch block. As Crockford says elsewhere, he feels that, "It is difficult to write correct programs while using idioms that are hard to distinguish from obvious errors."
1.) ex used (okay)
So (as I'm guessing you know) if you write this code and do something with ex, jslint doesn't complain.
/*jslint browser: true, white:true, sloppy:true*/
var spam;
try {
spam = "spam";
} catch (ex) {
window.alert(ex);
}
2.) ex unused means ignore (okay too)
So if you mean not to do anything with ex, he wants the code to tell folks you didn't screw up by leaving your ex equivalent in there by naming that variable ignore.
/*jslint browser: true, white:true, sloppy:true*/
var spam;
try {
spam = "spam";
} catch (ignore) {
}
3.) ignore used (error!)
So, in typical Crockfordian fashion, you now can't use ignore and actually do something in the catch block!
/*jslint browser: true, white:true, sloppy:true*/
var spam;
try {
spam = "spam";
} catch (ignore) {
window.alert(ignore);
}
That gives
Unexpected 'ignore'. } catch (ignore) {
Just another hyper-explicit "don't make code that looks like an error" move by Crockford.
(Aside: Might be fun to take a look at Why are empty catch blocks a bad idea while you're on the subject. Honestly, though ignore is probably a useful convention, based on that discussion (I mean, it includes Skeet arguing against empty catch blocks!), I'm a little surprised Crockford allows the ignore kludge, as the above link has arguments that feel a lot like his for calling some regular expressions "unsafe".)

Yii trace - proper usage

Unit testing and xdebug usage aside, I wish to have a way to throw some browser message is a value is not expected to be present.
Let's say: $className = 45;
If we have:
public function setMainClass($className) {
if (is_string($className)) {
$this->_mainClass = $className;
} else {
echo Yii::trace(CVarDumper::dumpAsString($className),'vardump');
}
}
We will get this output to the browser on development stage.
It's great.
I'm not sure however, if this is a proper way of use Yii::trace of if I'm miss using it.
Please advice.
It is not necessary to echo the call Yii::trace() (it returns void so the echo does nothing). The other recommendation is that you might consider changing category to resemble a path alias as discussed in the documentation. For example-
} else {
Yii::trace(CVarDumper::dumpAsString($className), 'application.models.MyGreatModel');
}