@@ -6,7 +6,9 @@ use crate::{
66 class:: RegisteredClass ,
77 error:: { Error , Result } ,
88 ffi:: zend_throw_exception_ex,
9+ ffi:: zend_throw_exception_object,
910 flags:: ClassFlags ,
11+ types:: Zval ,
1012 zend:: { ce, ClassEntry } ,
1113} ;
1214
@@ -25,6 +27,7 @@ pub struct PhpException {
2527 message : String ,
2628 code : i32 ,
2729 ex : & ' static ClassEntry ,
30+ object : Option < Zval > ,
2831}
2932
3033impl PhpException {
@@ -36,7 +39,12 @@ impl PhpException {
3639 /// * `code` - Integer code to go inside the exception.
3740 /// * `ex` - Exception type to throw.
3841 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+ }
4048 }
4149
4250 /// Creates a new default exception instance, using the default PHP
@@ -59,10 +67,25 @@ impl PhpException {
5967 Self :: new ( message, 0 , T :: get_metadata ( ) . ce ( ) )
6068 }
6169
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+
6282 /// Throws the exception, returning nothing inside a result if successful
6383 /// and an error otherwise.
6484 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+ }
6689 }
6790}
6891
@@ -146,3 +169,44 @@ pub fn throw_with_code(ex: &ClassEntry, code: i32, message: &str) -> Result<()>
146169 } ;
147170 Ok ( ( ) )
148171}
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