Migrating to v0.14
New Macro Transition
The old macro system used a global state to be able to automatically register
functions and classes when the #[php_module]
attribute is used. However,
global state can cause problems with incremental compilation and is not
recommended.
To solve this, the macro system has been re-written but this will require changes to user code. This document summarises the changes.
There is no real changes on existing macros, however you will now need to register functions, classes, constants and startup function when declaring the module.
#[php_module(startup = "startup_function")]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module
.class::<TestClass>()
.function(wrap_function!(hello_world))
.constant(wrap_constant!(SOME_CONSTANT))
}
Functions
Mostly unchanged in terms of function definition, however you now need to register the function with the module builder:
use ext_php_rs::prelude::*;
#[php_function]
pub fn hello_world() -> &'static str {
"Hello, world!"
}
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module
.function(wrap_function!(hello_world))
}
Supported #[php]
attributes:
#[php(name = "NEW_NAME")]
- Renames the function#[php(rename = case)]
- Changes the case of the function name#[php(vis = "public")]
- Changes the visibility of the function#[php(defaults(a = 5, test = 100))]
- Sets default values for function arguments#[php(variadic)]
- Marks the function as variadic. The last argument must be a&[&Zval]
Classes
Mostly unchanged in terms of the class and impl definitions, however you now need to register the classes with the module builder:
use ext_php_rs::prelude::*;
#[php_class]
#[derive(Debug)]
pub struct TestClass {
#[php(prop)]
a: i32,
#[php(prop)]
b: i32,
}
#[php_impl]
impl TestClass {
#[php(name = "NEW_CONSTANT_NAME")]
pub const SOME_CONSTANT: i32 = 5;
pub const SOME_OTHER_STR: &'static str = "Hello, world!";
pub fn __construct(a: i32, b: i32) -> Self {
Self { a: a + 10, b: b + 10 }
}
#[php(defaults(a = 5, test = 100))]
pub fn test_camel_case(&self, a: i32, test: i32) {
println!("a: {} test: {}", a, test);
}
fn x(&self) -> i32 {
5
}
pub fn builder_pattern(
self_: &mut ZendClassObject<TestClass>,
) -> &mut ZendClassObject<TestClass> {
dbg!(self_)
}
}
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module
.class::<TestClass>()
}
Supported #[php]
attributes (struct
):
#[php(name = "NEW_NAME")]
- Renames the class#[php(rename = case)]
- Changes the case of the class name#[php(vis = "public")]
- Changes the visibility of the class#[php(extends = "ParentClass")]
- Extends a parent class#[php(implements = "Interface")]
- Implements an interface#[php(prop)]
- Marks a field as a property
Supported #[php]
attributes (impl
):
#[php(rename_consts = case)]
- Changes the case of the constant names. Can be overridden by attributes on the constants.#[php(rename_methods = case)]
- Changes the case of the method names. Can be overridden by attributes on the methods.
For elements in the #[php_impl]
block see the respective function and constant attributes.
Constants
Mostly unchanged in terms of constant definition, however you now need to register the constant with the module builder:
use ext_php_rs::prelude::*;
#[php_const]
const SOME_CONSTANT: i32 = 100;
#[php_const]
#[php(name = "HELLO_WORLD")]
const SOME_OTHER_CONSTANT: &'static str = "Hello, world!";
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module
.constant(wrap_constant!(SOME_CONSTANT)) // SOME_CONSTANT = 100
.constant(wrap_constant!(SOME_OTHER_CONSTANT)) // HELLO_WORLD = "Hello, world!"
.constant(("CONST_NAME", SOME_CONSTANT, &[])) // CONST_NAME = 100
}
Supported #[php]
attributes:
#[php(name = "NEW_NAME")]
- Renames the constant#[php(rename = case)]
- Changes the case of the constant name#[php(vis = "public")]
- Changes the visibility of the constant
Extern
No changes.
use ext_php_rs::prelude::*;
#[php_extern]
extern "C" {
fn phpinfo() -> bool;
}
fn some_rust_func() {
let x = unsafe { phpinfo() };
println!("phpinfo: {x}");
}
Startup Function
The #[php_startup]
macro has been deprecated. Instead, define a function with
the signature fn(ty: i32, mod_num: i32) -> i32
and provide the function name
use ext_php_rs::prelude::*;
fn startup_function(ty: i32, mod_num: i32) -> i32 {
0
}
#[php_module(startup = "startup_function")]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module
}
#[php]
Attributes
Attributes like #[rename]
or #[prop]
have been moved to the #[php]
attribute.
The #[php]
attribute on an item are combined with each other. This means that
the following variants are equivalent:
#[php(rename = case)]
#[php(vis = "public")]
#[php(rename = case, vis = "public")]