summaryrefslogtreecommitdiff
path: root/documentation/exceptions.html
blob: 5d136d9372afebf2522a48d58739310c7a849c75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<h1>Exceptions</h1>
<p>
    PHP and C++ both support exceptions, and with the PHP-CPP library exception
    handling between these two languages has become completely transparent.
    Exceptions that you throw in C++ are automatically passed on to the PHP
    script, and exceptions thrown by PHP scripts can be caught by your C++
    code as if it was a plain C++ exception.
</p>
<p>
    Let's start with a simple C++ function that throws an exception.
</p>
<p>
<pre class="language-c++"><code>#include &lt;phpcpp.h&gt;

Php::Value myDiv(Php::Parameters &params)
{
    // division by zero is not permitted, throw an exception when this happens
    if (params[1] == 0) throw Php::Exception("Division by zero");

    // divide the two parameters
    return params[0] / params[1];
}

extern "C" {
    PHPCPP_EXPORT void *get_module() {
        static Php::Extension extension("my_extension", "1.0");
        extension.add("myDiv", myDiv, {
            Php::ByVal("a", Php::Type::Numeric, true),
            Php::ByVal("b", Php::Type::Numeric, true)
        });
        return extension;
    }
}</code></pre>
</p>
<p>
    And once again you see a very simple extension. In this extension a "myDiv"
    function is created that divides two numbers. But division by zero is of
    course not allowed, so when an attempt is made to divide by zero, an
    exception is thrown. The following PHP script uses this:
</p>
<p>
<pre class="language-php"><code>
&lt;?php
try
{
    echo(myDiv(10,2)."\n");
    echo(myDiv(8,4)."\n");
    echo(myDiv(5,0)."\n");
    echo(myDiv(100,10)."\n");
}
catch (Exception $exception)
{
    echo("exception caught\n");
}
?&gt;
</code></pre>
</p>
<p>
    The output of this script is as follows:
</p>
<p>
<pre>
5
2
exception caught
</pre>
</p>
<p>
    The example shows how amazingly simple it is to throw exceptions from your
    C++ code, and catch them in your PHP script. Just as if you're not even
    working in two different languages at the same time, you can simply throw
    a Php::Exception object, and catch it in the PHP script.
</p>
<h2>Catching exceptions in C++</h2>
<p>
    But it works the other way around too. If your extensions calls a PHP 
    function, and the function happens to throw an exception, you can catch it
    just as if it was a normal C++ exception. 
</p>
<p>
<pre class="language-c++"><code>#include &lt;phpcpp.h&gt;

Php::Value callMe(Php::Parameters &params)
{
    // prevent that exceptions bubble up
    try
    {
        // call the function that was supplied by the user
        return params[0]();
    }
    catch (Php::Exception &exception)
    {
        return "Exception caught!";
    }
}

extern "C" {
    PHPCPP_EXPORT void *get_module() {
        static Php::Extension extension("my_extension", "1.0");
        extension.add("callMe", callMe, {
            Php::ByVal("callback", Php::Type::Callable, true)
        });
        return extension;
    }
}</code></pre>
</p>
<p>
    This code calls for explanation. As we've mentioned before, a Php::Value object can
    be used just like a normal PHP $variable is used, and you can thus store 
    integers, strings, objects, arrays, et cetera in it. But this also means
    that you can use it to store functions - because PHP variables can 
    be used to store function too! And that's exactly what we're doing here.
</p>
<p>
    The callMe() function from this example extension receives one single
    parameter: a callback function that it will immediately call, and whose
    return value is returned. If this callback function (which was supplied by
    the user) throws an exception, it is detected by the callMe() function, and
    it will return an alternative string ("Exception caught!") in stead.
</p>
<p>
<pre class="language-php"><code>
&lt;?php

// call "callMe" for the first time, and supply a function that returns "first call"
echo(callMe(function() {
    return "first call";
}));

// call "callMe" for the second time, but throw an exception this time
echo(callMe(function() {
    throw new Exception("Sorry...");
    return "second call";
}));
</code></pre>
</p>
<p>
    This PHP script uses our extension and calls the callMe() function two times
    in a row. First with a normal function that returns a string, but then with
    a function that throws an exception - which will be caught by the extension.
</p>