I access a function in an included class Environment which can throw an Alert which needs to direct the users back to a page with some error information. What is the best way for me to reference the page so it can be used wherever I access the function from anywhere?
Is there any better way to do what I am trying to do?
public function checkEnvironment() {
try {
// If status is false
if (!$this->getStatus()) {
// Generate a new special exception with code
throw new Alert(6);
} else {
$connection = Gateway::checkInstance();
return $connection->getData('SELECT * FROM control_environment WHERE subdomain = ?', array($this->subdomain[0]));
}
} catch (Alert $alert) {
$_SESSION['error'] = $alert->getData();
if (!headers_sent()) {
header('Location: my/file/here.php');
exit;
}
}
}
You're badly abusing exceptions. There is absolutely no reason to put a single if statement in a try block, which can only throw one type of exception which is guaranteed to be caught immediately after that block. You've added nothing to your code but clutter, there is literally no advantage to doing this over simply doing an if/else with no exceptions/catching.
The point of exceptions is that you throw them up out of the current scope, to some place where they can actually be handled in a meaningful way.
Pick a real exception class, one that communicates something about the error that's occurred. Alert(6) doesn't tell anybody anything. Then, handle that (and probably many other) exceptions up above this, where you can be more sure that redirecting is the correct course of action. Your low-level database code shouldn't have any concept of browsers or http or redirection.
Your code also shouldn't have an else branch when the purpose of the if branch is to throw an exception. The else is redundant.
The whole function should look like this.
public function checkEnvironment() {
if (!$this->getStatus())
// Generate a new special exception with code
throw new StatusException;
$connection = Gateway::checkInstance();
return $connection->getData('SELECT * FROM control_environment WHERE subdomain = ?', array($this->subdomain[0]));
}
Related
I need some function that will accept a function as the parameter and will run it in try {} catch (Exception $e) {}. If it runs successfully, do nothing, otherwise, throw new Exception. That's something like function-checker, which checks functions if they ran successfully. Anybody can help me or give advice?
Thanks for any replies.
The function should work like that:
function itwillfail () {
echo 10 / 0;
}
check("itwillfail");
Output: Caught exception: Custom exception text here, because it has been thrown as custom.
("check" is that function I need)
What I tried:
function check($func) {
try {
call_user_func($func);
} catch (Exception $e) {
throw new Exception("Custom text here.");
}
}
EDIT: More explained: I need to create function, which do the same as "try" and a lot of different "catch"es for different types of exceptions.
Summarizing your question:
You want a way to call a custom function from a string variable (which you have already figured out that would be via call_user_func($var);.
You then want that function to throw a custom exception error
Confused
What is not clear is the reason you would opt to not define your error handler using the set_error_handler function which would effectively do what your asking and set a switch statement to output different messages based on the error generated.
Example
The following example is not using a call_user_func but it effectively allows you to write how the error will be handled
<?php
function myerror($error_no, $error_msg) {
echo "Error: [$error_no] $error_msg ";
echo "\n Now Script will end";
die();
}
// Setting set_error_handler
set_error_handler("myerror");
$a = 10;
$b = 0;
// Force the error
echo($a / $b);
?>
Not every function throws an exception when they fail. Many functions, especially ones that have been around for a long time, simply trigger PHP errors rather than exceptions.
To handle those, you would use a custom error handler:
https://www.php.net/manual/en/function.set-error-handler.php
So you could set up a custom error handler that would intercept those kinds of failures and throw them as exceptions. The whole point of that function is to do what you're trying to do - handle errors in a custom way.
I have a query with try-catch block. I am going to create object and if it fails it will throw error message or say redirect on some other page.
Code
function __construct() {
try{
$this->ServiceObj = AnyClass::getService('XXX');
}
catch{
return Redirect::to('/');
}
}
public function MyOwnFunction() {
$getValueofCode = $this->_ServiceObj->set($endPoint_Url); //it's only example method not want to set anything
}
Is this correct way to define and use the try catch block in a constructor? Can I use try & catch block in construction? If NO than is there a better way to achieve this?
Thanks in Advance!!!
You can definitely use try catch in a constructor, just don't forget to specify the exception class you want to catch like catch (\Exception $e). However Laravel will not process the returned redirect. (By definition constructors shouldn't even return something)
An easy fix for this would be calling send() on the redirect. This will return it immediately to the client and stop the app.
try{
$this->ServiceObj = AnyClass::getService('XXX');
}
catch(\Exception $e){
Redirect::to('/')->send();
}
But since you mentioned a login page, you might be better of using a before filter to check and redirect. Like the built in auth filter does.
A third solution would be App::error. In app/start/global.php you could do something like this:
App::error(function(FooBarException $exception)
{
return Redirect::to('/');
});
Of course this only works if your exception is specific enough (replace FooBarException with the exception you want to catch)
Regarding function calls, is it better to give the caller the responsibility of checking if a function worked or failed, or should the error be announced by the function itself?
The reason I'm asking is because I don't like mixing presentation with logic, however if the caller has to error-check, it can be inaccurate and cumbersome eg.
if(!login($username, $password)
{
echo 'Login failed. Please try again.';
}
The caller has no idea why it failed. Was the username/password combo wrong, or was it a database connection failure? Or some other unexpected reason?
This would not be a problem if we can error check/throw exceptions inside the functions, because then we would have specific errors at specific points of code eg database connection failures...but that would be mixing presentation and logic. What is the best practice here?
Thank you.
I would personally give the caller the responsibility by throwing an exception in the business logic (model) layer. Then, the exception can be caught in the controller (and the error assigned a variable in the view). Some people even like to catch exceptions directly in the presentation layer, but this does not apply well in the case of web development. As long as the exception is only used for presentation purposes in the view, I don't consider it much of a problem, though.
So, I would not do as you did in your simple example, because the caller may not always want an error to be displayed. By handling the responsibility to the caller, he or she has a choice. Also, I don't like echoing content in the business logic (I prefer to throw exceptions and keep the models clean from presentation), but your code was most likely just an oversimplified example.
Edit: You could do something like this:
Model:
function login($username, $password) {
if (login failed) {
throw new Login_Exception();
}
else {
// Set session
return true;
}
}
Controller:
try {
$model->login($username, $password);
}
catch (Login_Exception $e) {
$view->loginError = 'There was an error logging in.';
}
You can then throw different exceptions to indicate exactly what went wrong (e.g. Wrong_Username_Exception) and handle it accordingly. Alternatively you could even provide a user friendly reason in the exception's constructor, but in my opinion that would be coupling presentation and logic a little too much.
The problem with your sample code:
if(!login($username, $password)
{
echo 'Login failed. Please try again.';
}
... is that the login() function doesn't return enough information for the caller to work with. This is a problem no matter whether the caller is a Web presentation layer, or something else.
A better login() function might return an Object, so that your caller could do:
$response = login($username, $password);
if(! $response->isLoggedIn()) {
echo "Login failed. " + $response->getErrorMessage();
}
Now your login method is not tightly coupled to the user interface, but you are able to pass a reason for the login failure to the user.
Now, it's valid to say that there is still "presentation" in the login() method, since the text returned by it is quoted verbatim to the user. If you want to be even more loosely coupled, you could define a list of error codes, and have your presentation layer translate those into messages. Or you could return a value that points into a message table. Read up on internationalization; it's the same basic domain.
The first one. The caller should have the responsability of error checking.
If you want to know what kind of error ocured you can rewrite the login function and add a third parameter which will hold a reference to the error, like this:
<?php
function login($user, $pass, &$error) {
// if user or pass wrong
$error = 'Username / pass wrong';
// if db failed
$error = 'unable to connect to db'
};
if(!login($user, $pass, $error)) {
// do whatever you want with the error
}
Better yet, you could use constants for the error types
UPDATE
You wouldn't want to show the error withing the function if you are setting sessions or cookies after you have called the function. It will break thins and you'll get notices like: "Headers already sent..."
I am utilizing Codeigniter.
I have developed a variety of features, and they work perfectly if used as intended.
One such script, a whois script checks the owner of a domain name.
If however the user types in an invalid domain name, all sorts of errors are being thrown up here there and everywhere.
For example, if a user types in stack.-com, this is of course not a valid domain. Thus when i call my helper which does the query, no result is return and a variety of errors are returned. There are also errors when i try to display an empty array to the user.
My question relates to errors.
I could use preg_match and check if the domain is valid. If not i set an error variable which i intend to output to the user.
However before my controller gets to the if else statement which decides whether to show the error page or the results page, the program is running queries, and accessing methods to get the data which were there no errors would get the data to pass to the result view.
I.E I know there is an error, but still lots of other errors are being shown because an invalid item is being passed to my other scripts.
With Codeigniter, and the MVC setup, what is the best way of catching the error and displaying it to the user without having to use exceptions which do the same thing over and over again?
Thanks
EDIT WITH IDEA
try
{
$this->load->model('whois');
$this->whois->process('domain.-com');
}
catch
{
$this->load->view('errors',$errordata);
$this->load->view('footer');
die;
}
$this->load->view('normal_content');
$this->load->view('footer');
Is this the suggested setup for using exceptions with codeigniter? within my model, the function will throw exceptions if there is a problem. The catch statement will then display them and die, thus not showing the content.. It does not seem right..?
Here's the way I usually handle this:
Post your form back to the same route
If there are errors, show the form again, with an error state
If everything passes, redirect NOW to the next step / success state
Sample code:
<?php
...
public function form()
{
if (strtoupper($this->input->server('REQUEST_METHOD')) == 'POST')
{
try {
// handle all your validation here
redirect('success_route');
exit;
}
catch (Exception $e)
{
// this could get a little fancier, but a simple solution is to pass the exception
// directly to the view. you could also load the `errors` view here, but return the
// content to a variable and pass to your full view
$this->load->vars('exception', $e);
}
}
$this->load->view('normal_content');
$this->load->view('footer');
}
...
You have to do as follows
1) database.php : $db['default']['db_debug'] = FALSE;
2) in your modal file
try {
$query_str = "SELECT * FROM `pro_property` WHERE username = '".$username."'";
$result = $this->db->query($query_str);
if (!$result)
{
throw new Exception('error in query');
return false;
}
return $result;
} catch (Exception $e) {
print_r($e);
}
I've been wondering why would I use Exceptions in my PHP. Let's take a look at a simple example:
class Worker
{
public function goToWork()
{
return $isInThatMood ?
// Okay, I'll do it.
true :
// In your dreams...
false;
}
}
$worker = new Worker;
if (!$worker->goToWork())
{
if (date('l',time()) == 'Sunday')
echo "Fine, you don't have to work on Sundays...";
else
echo "Get your a** back to work!";
}
else
echo "Good.";
Is there a reason for me to use Exceptions for that kind of code? Why? How would the code be built?
And what about code that may produce errors:
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return false;
return file_get_contents($file);
}
}
Why would I use Exceptions in the above case? I have a feeling that Exceptions help you to recognize the type of the problem, which occured, true?
So, am I using Exceptions appropriately in this code:
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return throw new Exception("File not found.",123);
try
{
$contents = file_get_contents($file);
}
catch (Exception $e)
{
return $e;
}
return $contents;
}
}
Or is that poor? Now the underlying code can do this:
$fo = new FileOutputter;
try
{
$fo->outputFile("File.extension");
}
catch (Exception $e)
{
// Something happened, we could either display the error/problem directly
echo $e->getMessage();
// Or use the info to make alternative execution flows
if ($e->getCode() == 123) // The one we specified earlier
// Do something else now, create "an exception"
}
Or am I completely lost here?
When should I use an exception?
You use an exception to indicate an exceptional condition; that is, something which prevents a method from fulfilling its contract, and which shouldn't have occurred at that level.
For example, you might have a method, Record::save(), which saves changes to a record into a database. If, for some reason, this can't be done (e.g. a database error occurs, or a data constraint is broken), then you could throw an exception to indicate failure.
How do I create custom exceptions?
Exceptions are usually named such that they indicate the nature of the error, for example, DatabaseException. You can subclass Exception to create custom-named exceptions in this manner, e.g.
class DatabaseException extends Exception {}
(Of course, you could take advantage of inheritance to give this exception some additional diagnostic information, such as connection details or a database error code, for example.)
When shouldn't I use an exception?
Consider a further example; a method which checks for file existence. This should probably not throw an exception if the file doesn't exist, since the purpose of the method was to perform said check. However, a method which opens a file and performs some processing could throw an exception, since the file was expected to exist, etc.
Initially, it's not always clear when something is and isn't exceptional. Like most things, experience will teach you, over time, when you should and shouldn't throw an exception.
Why use exceptions instead of returning special error codes, etc?
The useful thing about exceptions is that they immediately leap out of the current method and head up the call stack until they're caught and handled, which means you can move error-handling logic higher up, although ideally, not too high.
By using a clear mechanism to deal with failure cases, you automatically kick off the error handling code when something bad happens, which means you can avoid dealing with all sorts of magic sentinel values which have to be checked, or worse, a global error flag to distinguish between a bunch of different possibilities.
I'm not a PHP programmer, but this looks similar to C#.
Typically you'd want to throw errors if it is a point of no return. Then you would be able to log something to show that the impossible happened.
If you can tell that the file doesn't exist then you could just say that. No real need in my mind to also throw an exception.
Now if the file was found and you are processing it, and say only half the file was uploaded and you had no way of telling that without an exception, then it'd be nice to have around.
I would say it's a good design practice to avoid the catch all exceptions "catch (Exception $e)" and design by contract instead, just like you seem to be doing in the prior example. I would at first be more specific with the type of exception being thrown and then work from there if needed. Otherwise, stay away from the try->catch and exceptions.
In no way can you assume that a file exists just because you called file_exists()! The function file_exists doesn't open the file, so the file can potentially be deleted or renamed or moved at any time!
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return false;
///<--- file may be deleted right here without you knowing it
return file_get_contents($file);//<-- then this will throw an error
//if you don't catch it, you're program may halt.
}
}
I believe this it better:
class FileOutputter
{
public function outputFile($file)
{
try{
if (!file_exists($file))
return false;
return file_get_contents($file);
}catch(Exception e){
check_what_went_wrong_and_go_to_plan_B();
}
}
}
(Edit: And it's probably even better to actually try to open the file from the beginning. If you succeed then you have a 'lock' on the file and it won't just disappear. If not, then catch the exception and see what went wrong.
Then again, you might feel that this level of reduncancy is just silly. In that case I don't think you need to worry about try/catch at all :)
Just a note really, your code for file outputter is invalid, since file_get_contents($file)
does not throw an exception. It will however raise a warning if the file doesn't exist, or can't be accessed for some reason. Additionally, you are returning an exception from outputFile, when you should probably be just letting the error propagate up the call stack.
However, you can register the error handler in php to throw exceptions when an error occurs:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
That way, any standard function calls that cause an error will throw an exception.
So, I would change FileOutputter to this (with that snippet above added):
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
throw new Exception("File not found.",123);
return file_get_contents($file);
}
}
The calling code is then basically the same.
Basically rule is not to return an Exception when an error occurs - you can catch it if you want, and throw a custom exception, but let the exception go up the call stack until you want to use it.