creating a simple exception for a class - php

I am creating a class called ex: foo
class foo{
function __construct($arg){
if(empty($arg)){
throw new fooException('argument can not be empty');
}
}
}
I tried to create the class without passing anything through the constructor like this
try{
$o = new foo();
}catch(FooException $e){
echo $e->getMessage();
}
I am getting error Fatal error: Class 'FooException' not found in ..
I realize that, I need to extend maybe the error exception class, but there are no examples on how to do this in SO.

Here's an example of defining a custom Exception called FooException.
The class that follows it, TestException tests this custom exception.
<?php
/**
* Define a custom exception class
*/
class FooException extends Exception
{
// Redefine the exception so message isn't optional
public function __construct($message, $code = 0, Exception $previous = null) {
// some code
// make sure everything is assigned properly
parent::__construct($message, $code, $previous);
}
// custom string representation of object
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
public function customFunction() {
echo "A custom function for this type of exception\n";
}
}
/**
* Create a class to test the exception
*/
class TestException
{
public $var;
const THROW_NONE = 0;
const THROW_CUSTOM = 1;
const THROW_DEFAULT = 2;
function __construct($avalue = self::THROW_NONE) {
switch ($avalue) {
case self::THROW_CUSTOM:
// throw custom exception
throw new FooException('1 is an invalid parameter', 5);
break;
case self::THROW_DEFAULT:
// throw default one.
throw new Exception('2 is not allowed as a parameter', 6);
break;
default:
// No exception, object will be created.
$this->var = $avalue;
break;
}
}
}
// Example 1
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (FooException $e) { // Will be caught
echo "Caught my exception\n", $e;
$e->customFunction();
} catch (Exception $e) { // Skipped
echo "Caught Default Exception\n", $e;
}
// Continue execution
var_dump($o); // Null
echo "\n\n";
// Example 2
try {
$o = new TestException(TestException::THROW_DEFAULT);
} catch (FooException $e) { // Doesn't match this type
echo "Caught my exception\n", $e;
$e->customFunction();
} catch (Exception $e) { // Will be caught
echo "Caught Default Exception\n", $e;
}
// Continue execution
var_dump($o); // Null
echo "\n\n";
// Example 3
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) { // Will be caught
echo "Default Exception caught\n", $e;
}
// Continue execution
var_dump($o); // Null
echo "\n\n";
// Example 4
try {
$o = new TestException();
} catch (Exception $e) { // Skipped, no exception
echo "Default Exception caught\n", $e;
}
// Continue execution
var_dump($o); // TestException
echo "\n\n";
?>
Source: http://www.php.net/manual/en/language.exceptions.extending.php
I modified it for your FooException

I see 2 things here, first, the exception you are throwing is called "fooException", and then, the one you are catching, is called "FooException", this is not correct, maybe a typo?. Another thing is, did you create a class named "FooException" and load it in your application?
require_once(path/to/FooExceptionClass.php);
Hope this helps.

Related

PHP: \Exception or Exception inside a namespace

I am trying to handle some errors in my api. However I tried some so many ways to execute what it's needed to it done?
In the code i used Exception, \Exception, another class extending to Exception, "use \Exception".
None of these options works.
What i need to do execute the block catch?
//Piece of source in the begin of file
namespace Business\Notifiers\Webhook;
use \Exception;
class MyException extends \Exception {}
//Piece of source from my class
try{
$products = $payment->getProducts();
if(count($products) == 0)
return;
$flight_id = $products[0]->flight_id;
$this->message = 'Sir, we have a new request: ';
$products = null; //Chagind it to null to force an error..
foreach($products as $product){
$this->appendAttachment(array(
'color' => '#432789',
'text' =>
"*Name:* $product->name $product->last_name \n" .
"*Total Paid:* R\$$product->price\n",
'mrkdwn_in' => ['text', 'pretext']
));
}
} catch(Exception $e){
$this->message = "A exception occurred ";
} catch(\Exception $e){
$this->message = "A exception occurred e";
} catch(MyException $e){
$this->message = "A exception occurred";
}
The accepted answer above give the real cause of the issue, but did not answer the topic
If in case someone is interested and is looking for
what is the difference between Exception and \Exception inside a namespace?
Still valid against PHP 7.3.5:
\Exception: Refer to Exception in root namespace
Exception: Refer to Exception in current namespace
PHP does not fall back to root namespace, if the class cannot be found in current name space, it emits an error.
<?php
namespace Business;
try {
throw new Exception("X"); // Uncaught Error: Class 'Business\Exception' not found
} catch (Exception $e) {
echo "Exception: " . $e->getMessage();
}
<?php
namespace Business;
class Exception extends \Exception {} // means \Business\Exception extends \Exception
$a = new Exception('hi'); // $a is an object of class \Business\Exception
$b = new \Exception('hi'); // $b is an object of class \Exception
First of all, you need to understand the difference between an exception and an error:
http://php.net/manual/en/language.exceptions.php
http://php.net/manual/en/ref.errorfunc.php
Trying to foreach over a null value will not yield an exception, but trigger an error. You can use an error handler to wrap an error in an exception, as such:
<?php
function handle ($code, $message)
{
throw new \Exception($message, $code);
}
set_error_handler('handle');
// now this will fail
try {
$foo = null;
foreach ($foo as $bar) {
}
} catch(\Exception $e) {
echo $e->getMessage();
}
However in your code, you can simply check if $products is null and if so, throw an exception:
if (!$products) {
throw new \Exception('Could not find any products')
}
foreach($products as $product) { ...

PHP: add a custom method to a(n internal) class (derived from exception class) at runtime

I extended the exception class amongst other things to add a method getMessageHTML().
In my application I want to catch any exception - also exceptions of derived internal classes like e.g. the ReflectionException - and want to be able to use a getMessageHTML() method or other custom methods on any exception and any derived exception.
Is there any way, to add a method or trait to an internal class like the exception class or the ReflectionException class at runtime?
The only solution that comes to my mind is to wrap any catched exception into my extended exception class like:
$anyException = new Exception(); //or ReflectionException, or ...
$wrappedException = MyException::wrap($anyException);
$wrappedException->getMessageHTML(); //or any other custom method
is there any implementation, that allows to introduce a method to every derived internal or foreign class/object, so that any object knows it?
$anyException = new Exception(); //or ReflectionException, or ...
$anyException->getMessageHTML();
then i could simply do:
try
{
throw <anyException>(); //like throw Exception() or throw ReflectionException() ...
}
catch($e)
{
$e->getMessageHTML(); //its assured that the method is known.
}
For now I am doing it like this:
class MyException extends Exception
{
protected static function cast($destination, $sourceObject)
{
if(is_string($destination))
$destination = new $destination();
$sourceReflection = new \ReflectionObject($sourceObject);
$destinationReflection = new \ReflectionObject($destination);
$sourceProperties = $sourceReflection->getProperties();
foreach($sourceProperties as $sourceProperty)
{
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationReflection->hasProperty($name))
{
$propDest = $destinationReflection->getProperty($name);
$propDest->setAccessible(true);
$propDest->setValue($destination,$value);
}
else
$destination->$name = $value;
}
return $destination;
}
public static function wrap(Exception $exception)
{
$wrap = $exception;
if(!$exception instanceof MyException)
$wrap = self::cast(__CLASS__, $exception);
return $wrap;
}
public function getMessageHTML()
{
//some code ...
}
}
try
{
throw new ReflectionException('test');
}
catch(Exception $e)
{
$e = MyException::wrap($e);
echo $e->getMessageHTML();
}
or - simpler - and with the advantage to have the previous exception available:
class MyException extends Exception
{
public static function wrap(Exception $exception)
{
$wrap = $exception;
if(!$exception instanceof AppException)
{
try
{
throw new AppException($exception->getMessage(), $exception->getCode(), $exception);
}
catch(AppException $e)
{
$wrap = $e;
}
}
return $wrap;
}
public function getMessageHTML()
{
//some code ...
}
}

How to print a message when an exception is thrown in a destructor triggered by exit() in php?

I have PHP code like this:
<?php
class MyDestructableClass {
function __destruct() {
print "Destroying MyDestructableClass";
throw new Exception('Intentionally thrown exception, can it be caught?');
}
}
$obj = new MyDestructableClass();
exit; // Triggers destructor eventually
?>
I want to print a special message when the destructor happens (and an exception is thrown) when the exit() occurs. I can't modify the contents of MyDestructableClass itself, I just want to notice when its destructor throws an exception.
I've tried an exception handler:
<?php
class MyDestructableClass {
function __destruct() {
print "Destroying MyDestructableClass";
throw new Exception('Intentionally thrown exception, can it be caught?');
}
}
$obj = new MyDestructableClass();
function myExceptionHandler($exception)
{
print "I noticed an exception was thrown, success!";
}
set_exception_handler('myExceptionHandler');
exit; // Triggers destructor eventually
?>
but nothing prints.
I've also tried a shutdown function:
<?php
class MyDestructableClass {
function __destruct() {
print "Destroying MyDestructableClass";
throw new Exception('Intentionally thrown exception, can it be caught?');
}
}
$obj = new MyDestructableClass();
function myShutdownFunction()
{
if (error_get_last() != NULL) // Only want to react to errors, not normal shutdown
{
print "I noticed an exception was thrown, success!";
}
}
register_shutdown_function('myShutdownFunction');
exit; // Triggers destructor eventually
?>
but nothing prints.
What technique can notice the exception in the destructor that is initiated by exit()?
This works for me. But I don't know if it is what you want.
<?php
class MyDestructableClass {
function __destruct() {
print "Destroying MyDestructableClass";
throw new Exception('Intentionally thrown exception, can it be caught?');
}
}
function RunEverything(){
$obj = new MyDestructableClass();
}
try {
RunEverything();
} catch (Exception $e){
echo 'My error has been thrown';
}
exit;
/*
*/
?

Why is my exception thrown from a closure not caught?

I've written a PHPUnit test that checks if an exception is thrown from a closure when a method is invoked. The closure function is passed in as an argument to the method with an exception being thrown from it.
public function testExceptionThrownFromClosure()
{
try {
$this->_externalResourceTemplate->get(
$this->_expectedUrl,
$this->_paramsOne,
function ($anything) {
throw new Some_Exception('message');
}
);
$this->fail("Expected exception has not been found");
} catch (Some_Exception $e) {
var_dump($e->getMessage()); die;
}
}
The code for the get function specified on the ExternalResourceTemplate is
public function get($url, $params, $closure)
{
try {
$this->_getHttpClient()->setUri($url);
foreach ($params as $key => $value) {
$this->_getHttpClient()->setParameterGet($key, $value);
}
$response = $this->_getHttpClient()->request();
return $closure($response->getBody());
} catch (Exception $e) {
//Log
//Monitor
}
}
Any ideas why the fail assert statement is called? Can you not catch exceptions thrown from closures in PHP or is there a specific way of dealing with them I don't know about.
For me the exception should just propagate out the return stack, but it doesn't appear to. Is this a bug? FYI I'm running PHP 5.3.3
Thanks for the answers...
Managed to figure out the issue. It looks like the problem is that the try-catch block that's being invoked is the one where the closure is invoked. Which makes sense...
So the code above should be
public function get($url, $params, $closure)
{
try {
$this->_getHttpClient()->setUri($url);
foreach ($params as $key => $value) {
$this->_getHttpClient()->setParameterGet($key, $value);
}
$response = $this->_getHttpClient()->request();
return $closure($response->getBody());
} catch (Exception $e) {
//Log
//Monitor
throw new Some_Specific_Exception("Exception is actually caught here");
}
}
So it looks like PHP 5.3.3 doesn't have a bug after all which was mentioned. My mistake.
I cannot reproduce the behavior, my example script
<?php
class Some_Exception extends Exception { }
echo 'php ', phpversion(), "\n";
$foo = new Foo;
$foo->testExceptionThrownFromClosure();
class Foo {
public function __construct() {
$this->_externalResourceTemplate = new Bar();
$this->_expectedUrl = '_expectedUrl';
$this->_paramsOne = '_paramsOne';
}
public function testExceptionThrownFromClosure()
{
try {
$this->_externalResourceTemplate->get(
$this->_expectedUrl,
$this->_paramsOne,
function ($anything) {
throw new Some_Exception('message');
}
);
$this->fail("Expected exception has not been found");
} catch (Some_Exception $e) {
var_dump('my exception handler', $e->getMessage()); die;
}
}
}
class Bar {
public function get($url, $p, $fn) {
$fn(1);
}
}
prints
php 5.4.7
string(20) "my exception handler"
string(7) "message"
as expected

php manual exception example

So I was reading the php manual on Extending Exceptions and read the example code. My question about the following code is: why does var_dump($o) evaluate to null? Is it because the constructor of the class TestException throws an exception, hence not allowing the completion of the object? I am almost certain that is the reason.
Nevertheless here is the code for examination:
<?php
/**
* Define a custom exception class
*/
class MyException extends Exception
{
// Redefine the exception so message isn't optional
public function __construct($message, $code = 0, Exception $previous = null) {
// some code
// make sure everything is assigned properly
parent::__construct($message, $code, $previous);
}
// custom string representation of object
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
public function customFunction() {
echo "A custom function for this type of exception\n";
}
}
/**
* Create a class to test the exception
*/
class TestException
{
public $var;
const THROW_NONE = 0;
const THROW_CUSTOM = 1;
const THROW_DEFAULT = 2;
function __construct($avalue = self::THROW_NONE) {
switch ($avalue) {
case self::THROW_CUSTOM:
// throw custom exception
throw new MyException('1 is an invalid parameter', 5);
break;
case self::THROW_DEFAULT:
// throw default one.
throw new Exception('2 is not allowed as a parameter', 6);
break;
default:
// No exception, object will be created.
$this->var = $avalue;
break;
}
}
}
// Example 1
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) { // Will be caught
echo "Caught my exception\n", $e;
$e->customFunction();
} catch (Exception $e) { // Skipped
echo "Caught Default Exception\n", $e;
}
// Continue execution
var_dump($o); // Null
?>
Have a look at PHP exception from PHP official site.
Example:
<?php
class MyException extends Exception { }
class Test {
public function testing() {
try {
try {
throw new MyException('foo!');
} catch (MyException $e) {
/* rethrow it */
throw $e;
}
} catch (Exception $e) {
var_dump($e->getMessage());
}
}
}
$foo = new Test;
$foo->testing();
?>

Categories