@@ -6,7 +6,9 @@ use crate::{
6
6
class:: RegisteredClass ,
7
7
error:: { Error , Result } ,
8
8
ffi:: zend_throw_exception_ex,
9
+ ffi:: zend_throw_exception_object,
9
10
flags:: ClassFlags ,
11
+ types:: Zval ,
10
12
zend:: { ce, ClassEntry } ,
11
13
} ;
12
14
@@ -25,6 +27,7 @@ pub struct PhpException {
25
27
message : String ,
26
28
code : i32 ,
27
29
ex : & ' static ClassEntry ,
30
+ object : Option < Zval > ,
28
31
}
29
32
30
33
impl PhpException {
@@ -36,7 +39,12 @@ impl PhpException {
36
39
/// * `code` - Integer code to go inside the exception.
37
40
/// * `ex` - Exception type to throw.
38
41
pub fn new ( message : String , code : i32 , ex : & ' static ClassEntry ) -> Self {
39
- Self { message, code, ex }
42
+ Self {
43
+ message,
44
+ code,
45
+ ex,
46
+ object : None ,
47
+ }
40
48
}
41
49
42
50
/// Creates a new default exception instance, using the default PHP
@@ -59,10 +67,25 @@ impl PhpException {
59
67
Self :: new ( message, 0 , T :: get_metadata ( ) . ce ( ) )
60
68
}
61
69
70
+ /// Set the Zval object for the exception.
71
+ ///
72
+ /// Exceptions can be based of instantiated Zval objects when you are throwing a custom exception with
73
+ /// stateful properties.
74
+ ///
75
+ /// # Parameters
76
+ ///
77
+ /// * `object` - The Zval object.
78
+ pub fn set_object ( & mut self , object : Option < Zval > ) {
79
+ self . object = object;
80
+ }
81
+
62
82
/// Throws the exception, returning nothing inside a result if successful
63
83
/// and an error otherwise.
64
84
pub fn throw ( self ) -> Result < ( ) > {
65
- throw_with_code ( self . ex , self . code , & self . message )
85
+ match self . object {
86
+ Some ( object) => throw_object ( object) ,
87
+ None => throw_with_code ( self . ex , self . code , & self . message ) ,
88
+ }
66
89
}
67
90
}
68
91
@@ -146,3 +169,44 @@ pub fn throw_with_code(ex: &ClassEntry, code: i32, message: &str) -> Result<()>
146
169
} ;
147
170
Ok ( ( ) )
148
171
}
172
+
173
+ /// Throws an exception object.
174
+ ///
175
+ /// Returns a result containing nothing if the exception was successfully
176
+ /// thrown.
177
+ ///
178
+ /// # Parameters
179
+ ///
180
+ /// * `object` - The zval of type object
181
+ ///
182
+ /// # Examples
183
+ ///
184
+ /// ```no_run
185
+ /// use ext_php_rs::prelude::*;
186
+ /// use ext_php_rs::exception::throw_object;
187
+ /// use crate::ext_php_rs::convert::IntoZval;
188
+ ///
189
+ /// #[php_class]
190
+ /// #[extends(ext_php_rs::zend::ce::exception())]
191
+ /// pub struct JsException {
192
+ /// #[prop(flags = ext_php_rs::flags::PropertyFlags::Public)]
193
+ /// message: String,
194
+ /// #[prop(flags = ext_php_rs::flags::PropertyFlags::Public)]
195
+ /// code: i32,
196
+ /// #[prop(flags = ext_php_rs::flags::PropertyFlags::Public)]
197
+ /// file: String,
198
+ /// }
199
+ ///
200
+ /// #[php_module]
201
+ /// pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
202
+ /// module
203
+ /// }
204
+ ///
205
+ /// let error = JsException { message: "A JS error occurred.".to_string(), code: 100, file: "index.js".to_string() };
206
+ /// throw_object( error.into_zval(true).unwrap() );
207
+ /// ```
208
+ pub fn throw_object ( zval : Zval ) -> Result < ( ) > {
209
+ let mut zv = core:: mem:: ManuallyDrop :: new ( zval) ;
210
+ unsafe { zend_throw_exception_object ( core:: ptr:: addr_of_mut!( zv) . cast ( ) ) } ;
211
+ Ok ( ( ) )
212
+ }
0 commit comments