Throwing exceptions in a PHP Try Catch block - php

I have a PHP function in a Drupal 6 .module file. I am attempting to run initial variable validations prior to executing more intensive tasks (such as database queries). In C#, I used to implement IF statements at the beginning of my Try block that threw new exceptions if a validation failed. The thrown exception would be caught in the Catch block. The following is my PHP code:
function _modulename_getData($field, $table) {
try {
if (empty($field)) {
throw new Exception("The field is undefined.");
}
// rest of code here...
}
catch (Exception $e) {
throw $e->getMessage();
}
}
However, when I try to run the code, it's telling me that objects can only be thrown within the Catch block.

function _modulename_getData($field, $table) {
try {
if (empty($field)) {
throw new Exception("The field is undefined.");
}
// rest of code here...
}
catch (Exception $e) {
/*
Here you can either echo the exception message like:
echo $e->getMessage();
Or you can throw the Exception Object $e like:
throw $e;
*/
}
}

To rethrow do
throw $e;
not the message.

Just remove the throw from the catch block — change it to an echo or otherwise handle the error.
It's not telling you that objects can only be thrown in the catch block, it's telling you that only objects can be thrown, and the location of the error is in the catch block — there is a difference.
In the catch block you are trying to throw something you just caught — which in this context makes little sense anyway — and the thing you are trying to throw is a string.
A real-world analogy of what you are doing is catching a ball, then trying to throw just the manufacturer's logo somewhere else. You can only throw a whole object, not a property of the object.

You tried to throw a string:
throw $e->getMessage();
You can only throw objects that implement \Throwable, e.g. \Exception.
As a sidenote: Exceptions are usually to define exceptional states of the application and not for error messages after validation. Its not an exception, when a user gives you invalid data

Throw needs an object instantiated by \Exception. Just the $e catched can play the trick.
throw $e

Related

How can I find out all the errors that can possibly be thrown by a block of PHP code?

I want to know what errors can be thrown that I am not catching, for dynamic code - not static code. For example, my code may run without throwing any Exceptions for 10 years and then throw UncaughtException
I want to specifically (non-generically) catch every type of Exception that can be thrown by the methods I am using. How can I know what Exceptions MAY be thrown by these methods?
I want to non-generically catch every type of error that can possibly be thrown for a section of PHP code.
Examples of exceptions that may be thrown:
PDOException
ExpiredException
Now I have this around everything:
try{
...
}catch(Exception $e){
...
}
I'd like to replace it with something like this:
try{
...
}catch(PDOException $e){
...
}catch(ExpiredException $e){
...
}catch(Exception $e){
...
}
I'd like to be confident that I am catching all different kinds of Exception that can be thrown by the methods in the section of code
And if I catch all Exceptions individually, will it be safe to remove this part?:
catch(Exception $e){
...
}
Or are there methods which will simply throw Exception?
My solution preference list (1 is the most-preferred solution):
1: A flag I can turn on that will cause php.exe to warn me about each and every possible type of Exception that is not specifically being caught
2: A way to individually check each method and see what errors can be thrown. Is the documentation the only way to check? or is there some IDE or PHP block that will tell me which Exceptions may be thrown by individual methods?
You can set callback function by using register_shutdown_function() which will call on every end of your php code execution. In this callback function you can check whether any error occurs or not using error_get_last().
For Example:
// Register shutdown function
register_shutdown_function("shutdownTracker");
// Define all error types you want to catch and handle
define('E_FATAL', E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR);
function shutdownTracker() {
$error = error_get_last(); // This will return empty if no error occurs while executing php code.
if(!empty($error) && ($error['type'] & E_FATAL)) {
// Write your code here to handle you error
}
}
Note: You should include this code on top of your code.
Well if you are talking exceptions, you already have the answer
try{
...
}catch(PDOException $e){
...
}catch(ExpiredException $e){
...
}catch(Exception $e){
echo get_class($e); // get's the class of unrecorded exceptions.
//catches any exceptions missed by the above
}
Now if you are talking about "errors" you can do is use a custom error handler
if(!function_exists('myErrorHandler')){
function myErrorHandler($severity, $message, $file = 'UNKNOWN', $line = 'UNKNOWN')
{
throw new ErrorException(
$message,
1,
$severity,
$file,
$line
);
}
set_error_handler('myErrorHandler');
}
What it does is convert all PHP errors to exceptions or rather to ErrorExceptoins.
Now you can go a step further and use these other two functions.
register_shutdown_function
AND
set_exception_handler
I'm actually working on porting what I use to it's own stand alone github project. Right after I finish my eJinn project, which you may be interested in. eJinn is designed to build exception classes based off a config file, so you can have one error per exception file and unique error codes in a project.
You can catch all exceptions without even call try.
function hello($e)
{
if ($e instanceof PDOException){
echo "something".
}else echo $e->getMessage();
}
set_exception_handler('hello');
this should catch all exceptions.
UPDATE 2
I've edited the code so you know what exceptions will be thrown using get_class();
class mycustomException extends Exception{} // making new exception
function hello($e)
{
if ($e instanceof PDOException){ // exception already known
echo "something";
}else{
echo get_class($e); // get exception name.
}
}
set_exception_handler('hello');
throw new mycustomException(); // throw exception that we made.

Why does the "catch" in try catch declare type of $e

try {
} catch (Exception $e) {
}
I thought PHP had type inference. Why is it neccesary to declare the type of the variable --$e-- ?
The code can throw different classes of exceptions. You can use that to your advantage to add proper code for error handling.
A try block can be followed by any number of catch blocks.
Example:
try
{
}
catch(\PDOException $e)
{
// Something bad happened while dealing with database
}
catch(\LengthException $e)
{
// Length exception occurred
}
catch(\Exception $e)
{
// The \Exception is the parent class for all exceptions, this handles anything not caught in above example
}
Using the above sample, you can take proper measures for handling errors depending on why they occurred. That means you can throw exceptions that you defined. It's the best if you don't overdo it and swap out entire error handling with exceptions. Exceptions occur when something abnormal in the code flow occurs, for example - a connection to MySQL broke mid-transaction.

Understanding try and catch

This probably sounds ridiculous. However, if you don't ask you'll never learn.
I'm relatively new to PHP and self-taught so I haven't exactly learnt everything "to the book".
Is the following required:
try {
}
catch {
}
Am I right in thinking that the try will try to "execute" the code within the brackets and the catch will try and catch the result of the outcome? If there is nothing to catch then it will throw an error?
The first assumption is correct: the code in try will be attempted to run.
However, if no error is thrown, then the block exits normally. If there is an error thrown, then the try execution ends early and goes into the catch block. So your second idea is switched.
try catch is used for exception handling or error handling.Put your script in try block and write your custom error message in catch block.
try{
// put here script
}catch(Exception $error){
//your custom message
echo 'Caught exception: ', $error->getMessage(), "\n";
}
If your script does not execute then it will be jump catch block and access message using $error object.
What is the benefit? The benefit is the whole script will not be stop to execute. It will be continue other block.
In the try block you execute code, whenever something fails in that block it will jump to the catch block. You usually define a variable holding the exception.
So to answer your question, no it will not process the catch block when there is nothing going wrong in the try block. (unless you specifically throw an exception)
try {
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Try block is hold the code which you want to execute. and Catch block is hold the code if you have cause any error then it will execute the catch code or error message.
Basically try and catch we are using for the error handling and avoid to break the control flow of the program and page.
Simple example:
<?php
class A {
public function getA($a = 0)
{
if ($a === 0) {
throw new ItCantBeZeroException("Message");
}
return $a;
}
}
// I want to throw default exception because I'm not sure
// am I doing it right or what can I do with bad parameter.
$a = new A;
echo $a->getA(0);
// Now, I know what I can do if developer write bad input.
// It can't be 0, so I just print my custom error message
// to my page.
try {
$a = new A;
echo $a->getA(0);
} catch (ItCantBeZeroException $e) {
echo "Parameter can't be zero. Try again.";
}
?>
You can define your own exceptions (like ItCantBeZeroException). Exceptions throw error on site (like "Message") but we can catch them and change to something we want.
You write simple class where some code must be string or integer between 0 and 20.
You use this code, but when user make variable 21, simple class throw error.
You refactor code to catch exception and try to fix code, e.g. change any integer greater than 20 to 20. Then code works properly.
Try and Catch is known as Exception Handling
According to w3schools:
Exceptions Handling are used to change the normal flow of a script if a specified error occurs.
For More:
http://www.w3schools.com/php/php_exception.asp

Custom messages for php exception handling

I'm using an external file with $errmsg array for displaying errors, like:
'app_init' => 'Cannot initialize application',
Using conditionals, I call the function to display the message on failure:
if(!$condition)
{
$arraywithmessages->functionforfiltering($err,'app_init',$aim);
}
...where $err is the array of messages, and $aim is predefined method of publishing error (e-mail, view, etc...)
Now I'd like to make use of Exception Handling, but I don't know where to start. Can anyone help? This doesn't seem to work:
try {
if (!$condition) {
throw new Exception('app_init');
}
// continue
} catch (Exception $e) {
$arraywithmessages->functionforfiltering($err,$e->getMessage(),$aim);
}
I don't know exactly what you want to achive but you should remember that try, catch should be used wisely. It should be used for Exceptional situations only. If you don't use them in that way then it's GOTO code.
About exceptions, remmeber that you can extend Exception class and make your own exceptions and catch them in multiple catch blocks, there is also finally block.
About the constructor of Exception. It has the second param which is $code you can use it to show proper message.
$err = array(0x1 => 'my error app init');
try {
if (!$condition) {
throw new Exception('app_init', 0x1);
}
// continue
} catch (Exception $e) {
echo $err[$e->getCode()]; //it shouldn't be only echo it should do some tries to fix the code close streams etc. not just echo.
}
There is also function
set_exception_handler(). which:
Sets the default exception handler if an exception is not caught within a try/catch block. Execution will stop after the exception_handler is called.
Consider using it. There are a lot of things that can be found in manual.

Detect if an exception has been thrown manually without using a custom exception class

I got a try-catch block in my php application like this:
try {
if ($userForgotToEnterField) {
throw new Exception('You need to fill in your name!');
}
...
doDifferentThingsThatCanThrowExceptions();
...
} catch (ExpectedException $e) {
$template->setError('A database error occured.');
} catch (Exception $e) {
$template->setError($e->getMessage());
}
I would like to only output $e->getMessage() for the exceptions I have manually thrown with a custom error text and not the ones that have been thrown by the other code as these might contain sensitive information or very technical info that the user should not see.
Is it possible to differentiate from a manually thrown exception and a random exception thrown by some method without using a custom exception class?
I agree that it might be best to just write your own exceptions. If for whatever reason you don't want to, you could set a custom error message and a custom error code (the second parameter for the Exception constructor.) Check each thrown Exception if the error code is yours, and display only those:
public Exception::__construct() ([ string $message = "" [,int $code = 0[, Exception $previous = NULL ]]] )
and then use getCode
I've thought about this a bit and I'd say that what you are doing DOES call for a custom exception class. If you want to get around it (which in the end is going to be more confusing), you would basically create a global (or same-scope) variable that all exceptions can modify, and in your throw block flag it.
$threwCustomException = false;
try {
if ($userForgotToEnterField) {
throw new Exception('You need to fill in your name!');
$threwCustomException = true;
}
...
doDifferentThingsThatCanThrowExceptions();
...
} catch (ExpectedException $e) {
$template->setError('A database error occured.');
} catch (Exception $e) {
if($threwCustomException){
//Whatever custom exception handling you wanted here....
}
$template->setError($e->getMessage());
}
That's the best I can think of. However, this is a bad idea, and it's the whole reason you are allowed to create your own exception classes. I know you're not looking for this answer, but since you look like you're trying not to create a TON of extra code, I would just extend Exception to "CustomException" or some other name specific to your project, and throw that for all cases, and handle it that way.
Hope that helps.

Categories