I'm trying to format user input with the following code:
$userInput="blalalbla";//assume the user is inputing wrong data, they are supposed to input it like "12:30"
try{
$timeStr=explode(":",$userInput);
$time=(new Datetime())->setTime($timeStr[0],$timeStr[1]);
}catch(ErrorException $e){
}
However, if the input is not in the right format, laravel4 will always fire an ErrorException and I have no way of catching it. Since the user input can be wrong in different ways, I thought this was the most elegant way of handling validation. As ridiculous as it sounds like, ErrorExceptions seem to be un-catchable. What other options do I have?
The actual error received in your code is a PHP Notice. You can't catch it because it isn't an exception at that point in time. Laravel defines the class Illuminate\Exception\Handler and uses PHP's set_error_handler() to turn PHP errors into ErrorExceptions.
To use a try/catch block in your controller, you'll have to throw the exception yourself in that area (or use code that throws exceptions). However, as most have commented, you should be doing appropriate input checking and sanitation prior to actually using the input in any code. Whether or not poor input throws exceptions is totally up to you.
set a global error handler
set_exception_handler (handler);
function handler($e) {
if($e instanceof TheExceptionYouWantToHandle) {
//then handle it
}
}
Related
This is a general question regarding exception handing for exceptions thrown in onther people's code.
I am using the following Codeigniter PHP library: https://github.com/sepehr/ci-mongodb-base-model
which relies upon this library for MongoDB: https://github.com/alexbilbie/codeigniter-mongodb-library/tree/v2
If I call a function in the first library, and it then calls one from the second. Sometimes the second library throws exceptions which I want to be able to deal with in my own code, but there is a try-catch statement around the exception throwing call, which means that it is dealt with before I get a chance to (I just prints the exception to the screen).
My question is:
Without modifying all of the functions in the first and second libraries (i.e. removing all of the try catches), how can I deal with the exception that is thrown?
EDIT
This is how the functions in the second library are arranged:
class SomeClass
{
function do_something()
{
...
try {
...
}
catch {
$this->_show_error('Update of data into MongoDB failed: ' . $exception->getMessage(), 500);
}
}
function _show_error($error_message = '', $response_code = 500)
{
//Inbuilt Codeigniter helper function which can be disabled from printing the error to the screen
show_error($error_message, $response_code);
}
}
Although I can disable the error from being printed (which is of course just for debugging), I still have no way of knowing that it occurred and handling it.
(should be a comment rather than an answer, but it's a bit long)
just prints the exception to the screen
Really? Are you sure?
Did you check it doesn't trigger an error instead of an exception and you're running this on a system which is not configured as a production server?
If so then I'd steer way clear of this as a library.
(I sincerely doubt anyone would write code that dumb and publish it without lots of warnings)
This is more of a architectural question. I like to know what people's opinion on how to properly handle errors in a fully Object Oriented PHP environment.
For example I have a class that retrieves all user data from the database. So I would use it in this way:
$userData = new UserDataConnection();
$userData->openDatabase();
$userData->retrieveData();
$userData->showData();
$userData->closeDatabase();
At each of these steps, an error could have potentially occurred. So would I return a boolean from each step stating whether the function has successfully executed (hence the error checking is within each function), or do I do a try-catch exception handling around the whole thing? or is there a better way?
Is it also better to always go to some kind of error page when some kind of error occur?
<?php
$ERROR = false;
try {
$userData = new UserDataConnection();
$userData->openDatabase();
$userData->retrieveData();
$DETAILS = $userData->showData();
$userData->closeDatabase();
} catch( Exception $e ) {
$ERROR = $e->getMessage(); // exit;
}
if( $ERROR ) {
$DETAILS = array();
}
?>
If you are using PDO you can throw a PDOException.
It typically boils down to a simple question:
May this function "legitimately" fail or is any failure a sign of something being really wrong?
If a function expects a certain kind of input and should never ever be called with a different kind of input, any failure to supply the correct input is an InvalidArgumentException. This is especially true for functions which do not directly handle user input. This works even better with type hinting.
If a function should always produce a certain result given the correct input, any failure of the function to produce that result is a RuntimeException or LogicException or some other kind of exception.
If a function may or may not produce some kind of result, false is a legitimate return value. Functions which deal with user input and therefore get very arbitrary input values are often fine with returning false.
Some examples:
getDatabaseConnection() is perfectly correct in throwing a RuntimeException or similar if it cannot establish a connection to the database. This is an exceptional circumstance in which case no work can continue.
transformFooIntoBar(Foo $foo) is correct in throwing some form of exception if it cannot return a Bar instance, for whatever reason that may be. The function has a clear purpose and a type checked input value. If it cannot do its job under such clear conditions, something is clearly wrong and must be fixed. Ergo, an exception.
checkIfUserExists($id) may well return false, because its job is to return a thumbs up or thumbs down. A user not existing is not an exceptional circumstance given this job description.
Where to catch a thrown exception depends on where you want to deal with it. Database connection errors should probably be caught at the very top of the call stack, since you probably cannot do anything if the database is down.
On the other hand, if some module is calling some submodule and half expects that submodule to fail and/or has a contingency plan in case it does fail, the module may catch the exception of the submodule and continue on doing its job. For instance getRSSUpdates() makes a call to a HTTP::fetchContents($url). If the URL returns a 404, the HTTP module may throw an exception, since it cannot return contents under these circumstances. The getRSSUpdates() function is prepared for this though and handles this case as "no updates at this time".
Building upon a question I already asked regarding exceptions, I fear that I might be writing php functions wrong then, or abusing the use of exceptions. The reason I say this, is because if custom exceptions are to be caught using try/catch blocks then the following function:
public function get_specific_page($page) {
if (!is_array( $this->_page )){
throw new AisisCore_Template_TemplateException( "<div class='error'>Trying to get a property from a non array.</div>" );
}
return $this->_page[$page];
}
Would then be called such as:
try{
get_specific_page($page);
}
catch(Exception $e){
echo $e->getMessage();
}
The problem with this approach is that I have many functions that are written like this, either checking to see if a file exists, throwing an error. Checking to see if a value is set in an array, throwing an error and my issue is that the file which deals with these function calls may become over loaded with try catch.....
So my question is, how would I better write functions like this so that I don't have php files over loaded with try catch statements, yet still be able to have y own custom functions.
Is it as obvious as writing the try catch inside the function it's self?
The reason I ask, if because I am use to working with fameworks and in companies where we write our functions as you see above. How ver I have worked with code bases that have tons of these functions and I dont see half the files that are useing them doing a bunch of try catches...
Update:
I was looking through zend source to better understand exceptions and came across this:
public function setMessage($messageString, $messageKey = null)
{
if ($messageKey === null) {
$keys = array_keys($this->_messageTemplates);
foreach($keys as $key) {
$this->setMessage($messageString, $key);
}
return $this;
}
if (!isset($this->_messageTemplates[$messageKey])) {
require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("No message template exists for key '$messageKey'");
}
$this->_messageTemplates[$messageKey] = $messageString;
return $this;
}
You can see how they throw a new exception message near the bottom, this function is not called by doing:
try{}catch(){}
yet when it throws an exception, there is no issue with "uncaught exception with message"
In my opinion, your approach is correct in general. However, a few notes:
You should refrain from using HTML formatting in exception messages. Generally, you don't know how the exception that you throw will be handled. For example, an exception handler could just write the message to a log file (you don't want HTML formatting then), present it to the user in a special error view (in which case the view itself should contain the HTML formatting), or simply ignore it (no need for formatting then, anyway).
Catch only exceptions that you can handle. If you know that your function throws an AisisCore_Template_TemplateException, you should just catch that exception and let all other exceptions bubble up to an exception handler that can handle them. You can use set_exception_handler to define such an exception handler that catches all uncaught exceptions by default (this is probably the case in your example from Zend Framework). Plainly put: Only catch exceptions in places where you know how to handle them.
Only use exceptions as what the name implies: to handle (unexpected) exceptions in your control flow. Using exceptions to control the regular flow of your program is possible, but generally considered bad design (just as a side note, your code samples look alright).
For the sake of completeness, some alternatives to using exceptions:
Use return codes instead of exceptions. This is old-school C-style. The advantage is that you don't need to wrap statements with try/catch-statements. However, you have to check the return values of each procedure, which is easy to forget. When using exceptions on the other hand, you reduce the risk of unexpected errors, since uncaught exceptions produce a fatal error per default.
Use PHP errors. See the trigger_error function for this. Custom errors are however nearly impossible to catch in PHP (except by using set_error_handler, which only works at global level).
During the process of my PHP learning I have been trying to read up on the best practices for error reporting and handling, but statements vary person to person and I have struggled to come up with a clear concise way of handling errors in my applications. I use exceptions on things that could go wrong, but for the most part it is hard for me to understand whether an exception should kill the application and display an error page or just be caught and silently dealt with.
Something that seems to elude me is, is there such thing as too much reporting? Every single time you call a function something could go horribly wrong meaning that if you were to confirm every single function call you would have to fill pages with if statements and work out what effect one failure may have on the rest. Is there a concise document or idea for error reporting that could clear this up for me? Are there best practices? What are the best examples of good error handling?
Currently I do the following:
Add important event results to an array to be logged and emailed to me if a fatal error was to occur
Display abstract/generic errors for fatal errors.
Use exceptions for cases that are likely to fail
Turn on error reporting in a development environment and off for live environment
Validate all user input data
Sanitizing invalid user input
Display concise, informative error messages to users without providing a platform for exploitation.
Exceptions are the only thing that you haven't understood IMHO: exceptions are meant to be out of your control, are meant to be caught be dealt with from outside the scope they are thrown in. The try block has a specific limit: it should contain related actions. For example take a database try catch block:
$array = array();
try {
// connect throws exception on fail
// query throws exception on fail
// fetch results into $array
} catch (...) {
$array[0]['default'] = 'me';
$array[0]['default2'] = ...;
...
}
as you can see I put every database related function inside the try block. If the connection fails the query and the fetching is not performed because they would have no sense without a connection. If the querying fails the fetching is skipped because there would be no sense in fetching no results. And if anything goes wrong, I have an empty $array to deal with: so I can, for example, populate it with default data.
Using exceptions like:
$array = array();
try {
if (!file_exists('file.php')) throw new Exception('file does not exists');
include('file.php');
} catch (Exception $e) {
trigger_error($e->getMessage());
}
makes no sense. It just a longer version of:
if (!file_exists('file.php')) trigger_error('file does not exists');
include('file.php');
I have been dealing with PHP since 2000, but not very actively, and my knowledge of PHP5 is quite horrible. Recently I got my interest for webdevelopment back after a 5 year long break, and I started working on a project. I wrote a class for that project that became fairly large, but so far without any specific error handling.
The purpose of the class is to parse HTML files with a specific layout and handle its data, and it was more or less a training exercise for me to get back into the game. I started to rewrite the class now, and I decided it was time to be a little more professional about error handling than simply using die(), which I have been using a lot so far. I think we can all agree that is a terrible direction to take. I want the class to be quite project independent, so that I can distribute it to whoever wants to use it.
The HTML files I want to parse contain tables with specific bordercolors, trs with specific bgcolors, but the number of elements are dynamic. To validate that the HTML files actually have this specific pattern, I have the following sample (pseudo)code
public function Validate() {
$tables = getall('table', $this->data);
foreach ($tables as $table) {
if ($table->bordercolor != 'navy' && $table->cellspacing != 0) {
// Error
}
foreach ($tables->tr as $tr) {
if ($tr->bgcolor != '#fff') {
// Error
}
}
}
return true;
}
Where it says // Error, the HTML layout doesn't check out and my class should not attempt to parse it. Traditionally I would do this:
if ($table->bgcolor != '#fff') {
$this->error = 'Invalid HTML layout';
return false;
}
And from where I call the method I would use
if ($class->Validate() === false) {
exit_with_error($class->GetError()); // Simple return of $this->error
}
I've always thought it's a decent approach because of it's simplicity. However that's also a disadvantage as it doesn't really provide any in-depth information of the error apart from the text itself. I can't see where the error was triggered, what methods were called, etc.
Since I resumed my PHP hobby I have discovered exceptions. My problem with them is simply that I don't understand how to properly use them. And if I should use them at all. I would like my class to be portable; can I use exceptions to handle errors at all? And if yes, how can I communicate the errors (i.e. translate my traditional error handling)? Or perhaps there is an even better approach to take, which I don't know about.
Any help appreciated :)
You are certainly thinking along the right path. Typically, I like to separatte class design from error handling logic. In other words I don't want to have a bunch of $this->error = 'something' logic in the class, as why would you want to add extra code to every class to store/handle/report errors.
Now you get into exceptions vs. errors and when to use each. This is likely a subject for debate, but my personal preference has largely been to throw Exceptions in cases where you get to a point in your code that you cannot recover from or do not have the logic to handle. A great example of this, that I typically use, is throwing Exceptions right at the beginning of any class method that requires parameters of a certain sort or value. Like this example:
public method set_attribute($value) {
if (empty($value)) {
throw new Exception('You must send me something');
} else if (!is_string($value)) {
throw new Exception("You sent me something but it wasn't the string I was expecting.");
}
// method logic here
}
Here if the caller didn't give us a non-empty string, we throw an Exception, as we were not expecting this and we can't guarantee successful completion of the method without a proper value. There is not reason to continue with the method at all. We send the caller the exception with a message about the problem. Hopefully they invoked this method in a try-catch block and can gracefully handle the exception and pass it along up the call stack. If not, your code just stopped execution with fatal error from an uncaught exception (something really easy to catch in testing).
Triggering errors, I honestly use a lot less, and typically use them more for debug, warning purposes. An example of this might be a deprecated method that you still want to work, but you want to give the user an error on
public function old_method() {
trigger_error('This method had been deprecated. You should consider not using it anymore.'. E_USER_WARNING);
// method logic
}
Of course you can trigger whatever level of E_USER class warning here yourself.
Like I said, I tend to work a lot more with Exceptions, as they are also easily extensible for easy use with logging and such. I almost always would have a custom Exception class extending from PHP's base Exception class that also provides logging, etc.
The other thing to consider is global error handling and Exceptoin handling. I strongly recommend using these and having these be some of the very first lines of code in any new project. Again, it will give you much better control over how you log errors/exceptions than what you can get by default.
I don't see a problem with how you are doing it, but If you want to dive into Exceptions, learn how to use try/catch statements. Usually it would be something like this:
try {
//some code that may cause an error here
} catch (Exception e) {
//if a error is found, or an exception is thrown in the try statement, whatever here will execute
//you can get the error message by using e->getMessage()
}
you can read more about it here: http://php.net/manual/en/language.exceptions.php