79

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.

starball
  • 20,030
  • 7
  • 43
  • 238
kaspnord
  • 1,403
  • 2
  • 18
  • 28

5 Answers5

115

Please note that this particular code example makes no sense, as you can simply remove the try-catch and have the same result:

function _modulename_getData($field, $table) {
    if (empty($field)) {
      throw new Exception("The field is undefined."); 
    }
    // rest of code here...
}

so Exception will be thrown and can be caught or handled elsewhere.

In case you are going to write some handling code, that may result in re-throwing the exception, you have to throw the Exception object, not a string returned by the getMessage() method:

function _modulename_getData($field, $table) {
  try {
    if (empty($field)) {
      throw new Exception("The field is undefined."); 
    }
    // rest of code here...
  }
  catch (Exception $e) {
    if (some condition) {
        // do some handling
    } else {
        // the error is irrecoverable
        throw $e;
    }
  }
}

or if you have to do some recovery, as it is often used with database transactions: do the recovery and then re-throw:

  catch (Exception $e) {
      $db->rollback(); // rollback the transaction
      throw $e; // let the error to be handled the usual way
    }
  }
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
AlienWebguy
  • 76,997
  • 17
  • 122
  • 145
73

To rethrow do

 throw $e;

not the message.

Chen Kinnrot
  • 20,609
  • 17
  • 79
  • 141
16

Just remove the throw if you are going to handle the error, or remove the try-catch block altogether, if all you need is the error message.

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.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
DaveRandom
  • 87,921
  • 11
  • 154
  • 174
8

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

rybo111
  • 12,240
  • 4
  • 61
  • 70
KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • What would be a better way to handle validations? Would IF statements be more appropriate in handling invalid user data? – kaspnord Jan 27 '12 at 23:08
  • In short: Yes. In long: Treat the occurence of invalid arguments like any other situation that can occur in your app and show an other useful (error-)page. `function validateField($validate) {return empty($validate);}` and somewhere for example `if validateField($x){ echo "Field is empty";}else{doSomethingUseful();}` – KingCrunch Jan 28 '12 at 00:15
  • 4
    @lazycommit "invalid data" is a little bit to general. If you mean "invalid values given from a user", than they are not invalid from the applications point of view, because the application _must_ expect this and therefore must treat them appropriate (--> validation). If you pass invalid data later during processing (from a backend, or because you didn't validate properly), then yes: Exception. To sum it up: Do not use `Exception`s for control flow (here: validation) :) – KingCrunch Jul 10 '13 at 21:17
  • You can only [`throw`](http://php.net/manual/en/internals2.opcodes.throw.php) objects, so `throw $e;` or `throw new \Exception( $e->getMessage() );`. – Ismail Jan 29 '18 at 09:00
0

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

throw $e
Goms
  • 2,424
  • 4
  • 19
  • 36