Attribute Macro ext_php_rs::php_function [−][src]
#[php_function]
Expand description
Attribute used to annotate a function as a PHP function.
Only types that implement FromZval
can be used as parameter and return types. These include
but are not limited to the following:
- Most primitive integers (
i8
,i16
,i32
,i64
,u8
,u16
,u32
,u64
,usize
,isize
) - Double-precision floating point numbers (
f64
) bool
String
Vec<T>
andHashMap<String, T>
whereT: FromZval
.Binary<T>
for passing binary data as a string, whereT: Pack
.Callable
for receiving PHP callables, not applicable for return values.Option<T>
whereT: FromZval
. When used as a parameter, the parameter will be deemed nullable, and will containNone
whennull
is passed. When used as a return type, ifNone
is returned theZval
will be set to null. Optional parameters must be of the typeOption<T>
.
Additionally, you are able to return a variant of Result<T, E>
. T
must implement
IntoZval
and E
must implement Into<PhpException>
. If an error variant is returned, a
PHP exception is thrown using the PhpException
struct contents.
You are able to implement FromZval
on your own custom types to have arguments passed in
seamlessly. Similarly, you can implement IntoZval
on values that you want to be able to be
returned from PHP fucntions.
Parameters may be deemed optional by passing the parameter name into the attribute options.
Note that all parameters that are optional (which includes the given optional parameter as well
as all parameters after) must be of the type Option<T>
, where T
is a valid type.
Generics are not supported.
Behind the scenes, an extern "C"
wrapper function is generated, which is actually called by
PHP. The first example function would be converted into a function which looks like so:
pub fn hello(name: String) -> String {
format!("Hello, {}!", name)
}
pub extern "C" fn _internal_php_hello(ex: &mut ExecutionData, retval: &mut Zval) {
let mut name = Arg::new("name", <String as FromZval>::TYPE);
let parser = ArgParser::new(ex)
.arg(&mut name)
.parse();
if parser.is_err() {
return;
}
let result = hello(match name.val() {
Some(val) => val,
None => {
PhpException::default("Invalid value given for argument `name`.".into())
.throw()
.expect("Failed to throw exception: Invalid value given for argument `name`.");
return;
}
});
match result.set_zval(retval, false) {
Ok(_) => {},
Err(e) => {
let e: PhpException = e.into();
e.throw().expect("Failed to throw exception: Failed to set return value.");
}
};
}
This allows the original function to continue being used while also being exported as a PHP function.
Examples
Creating a simple function which will return a string. The function still must be declared in the PHP module to be able to call.
#[php_function]
pub fn hello(name: String) -> String {
format!("Hello, {}!", name)
}
Parameters can also be deemed optional by passing the parameter name in the attribute options.
This function takes one required parameter (hello
) and two optional parameters (description
and age
).
#[php_function(optional = "description")]
pub fn hello(name: String, description: Option<String>, age: Option<i32>) -> String {
let mut response = format!("Hello, {}!", name);
if let Some(description) = description {
response.push_str(format!(" {}.", description).as_ref());
}
if let Some(age) = age {
response.push_str(format!(" I am {} year(s) old.", age).as_ref());
}
response
}
Defaults can also be given in a similar fashion. For example, the above function could have
default values for description
and age
by changing the attribute to the following:
#[php_function(optional = "description", defaults(description = "David", age = 10))]
pub fn hello(name: String, description: String, age: i32) -> String {
format!("Hello, {}! {}. I am {} year(s) old.", name, description, age)
}