EmielBruijntjes/PHP-CPP — pull request #9 by Photonios (2013-12-01 03:03:34+00:00)
Title: Added: extended exception support, inheritance, extended object support and callable types (callbacks)

In my last pull request you requested a better way to throw and catch exceptions. I'm happy to report that I have successfully implemented complete exception support and more :)

You can now safely throw PHP exceptions from PHP-CPP:

```CPP
throw Php::Exception("This is an exception!");
```

This exception will be caught before any code is executed in the PHP user space. When an exception is caught, it is rethrown as a PHP exception. Which can easily be catched from PHP:

```php
try
{
MethodThatCauseCppExcp();
}
catch(Exception $e)
{
echo "Caught exception: " . $e->getMessage();
}
```

But, what are exceptions good for when you can't create your own? This is way I implemented inheritance. It is now possible to inherit from another class. This means that all functionality of previously defined class is added to another. This works like this:

```CPP
extension.add("MyAwesomeClass", add("MyAwesomeBaseClass", Php::Class(
{
Php::Public("jeej", Php::Method(&MyAwesomeBaseClass::jeej))
}),
Php::Class(
{
Php::Public("top_class", Php::Method(&MyAwesomeClass::top_class))
}));
```

In this case, `MyAwesomeClass` inherits from `MyAwesomeBaseClass`, which makes the following possible:

```php
$awesomeness = new MyAwesomeClass();
$awesomeness->jeej(); // inherited from MyAwesomeBaseClass
```

All exceptions PHP must inherit from the `Exception` class. The same goes for exceptions in PHP-CPP. To register a custom exception class:

```CPP
class MyNewException : Php::Exception
{
public:
MyNewException() : Php::Exception()
{
}

MyNewException(const std::string &message) : Php::Exception(message)
{
}

virtual std::string GetExportName()
{
return "MyNewException";
}
};
```

To register the class:

```CPP
extension.add("MyNewException", extension.GetExceptionBase(), Php::Class() {});
```

You can now throw MyNewException from C++, and catch it in PHP!

Now, for catching exceptions thrown in PHP; that's impossible. I have researched it and it's IMPOSSIBLE. It can't be done. There's `zend_try` and associated macro's, but they only catch internal errors caused by `zend_error(..)`.
We can also NOT do some trick by using `zend_string_eval` to setup an exception handler for uncaught exceptions because when an unhandeld exception is thrown, excution STOPS. Even though it's impossible, it was an insane and stupid idea. Because, what happends when the user throws an exception in his callback, with the intention of terminating the execution? Wouldn't it be a huge violation of design if PHP-CPP caught the exception?

Now, the situation with a callback, that's something that wasn't possible yet. I have succesfully implemented callbacks, and the situation you described in the comment on my previous pull request is now possible:

```CPP
void MyCppFunction(Php::Parameters ¶ms)
{
// do not continue if not callable
if(!params[0].isCallable())
throw Php::Exception("Parameter 0 must be a callable type!");

Php::Value return_value = params[0].call({"this is a string!"});
std::cout << "Callback returned: " << return_value.stringValue(); << std::endl;
}
```

```PHP
MyCppFunction(function($str)
{
return "heyyy!";
});
```

Output:

```
Callback returned: heyyy!
```

As for `ObjectInfo`, see my previous pull request.

My apologies for the long story :p

For some in-depth talk, see the notes I made during development:

https://github.com/Photonios/PHP-CPP/wiki/Implementing-exceptions-into-PHP-CPP

Enjoy :D