pub struct ModuleBuilder<'a> { /* private fields */ }Expand description
Builds a Zend module extension to be registered with PHP. Must be called
from within an external function called get_module, returning a mutable
pointer to a ModuleEntry.
use ext_php_rs::{
builders::ModuleBuilder,
zend::{ModuleEntry, StaticModuleEntry},
info_table_start, info_table_end, info_table_row
};
#[unsafe(no_mangle)]
pub extern "C" fn php_module_info(_module: *mut ModuleEntry) {
info_table_start!();
info_table_row!("column 1", "column 2");
info_table_end!();
}
#[unsafe(no_mangle)]
pub extern "C" fn get_module() -> *mut ModuleEntry {
static MODULE: StaticModuleEntry = StaticModuleEntry::new();
MODULE.get_or_init(|| {
let (entry, _startup, owned) = ModuleBuilder::new("ext-name", "ext-version")
.info_function(php_module_info)
.try_into()
.unwrap();
(entry, owned)
})
}Implementations§
Source§impl ModuleBuilder<'_>
impl ModuleBuilder<'_>
Sourcepub fn new(name: impl Into<String>, version: impl Into<String>) -> Self
pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self
Creates a new module builder with a given name and version.
§Arguments
name- The name of the extension.version- The current version of the extension.
Sourcepub fn startup_function(
self,
func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32,
) -> Self
pub fn startup_function( self, func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32, ) -> Self
Sets the startup function for the extension.
§Arguments
func- The function to be called on startup.
Sourcepub fn shutdown_function(
self,
func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32,
) -> Self
pub fn shutdown_function( self, func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32, ) -> Self
Sets the shutdown function for the extension.
§Arguments
func- The function to be called on shutdown.
Sourcepub fn request_startup_function(
self,
func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32,
) -> Self
pub fn request_startup_function( self, func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32, ) -> Self
Sets the request startup function for the extension.
§Arguments
func- The function to be called when startup is requested.
Sourcepub fn request_shutdown_function(
self,
func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32,
) -> Self
pub fn request_shutdown_function( self, func: unsafe extern "C" fn(_type: i32, _module_number: i32) -> i32, ) -> Self
Sets the request shutdown function for the extension.
§Arguments
func- The function to be called when shutdown is requested.
Sourcepub fn post_deactivate_function(
self,
func: unsafe extern "C" fn() -> i32,
) -> Self
pub fn post_deactivate_function( self, func: unsafe extern "C" fn() -> i32, ) -> Self
Sets the post request shutdown function for the extension.
This function can be useful if you need to do any final cleanup at the very end of a request, after all other resources have been released. For example, if your extension creates any persistent resources that last beyond a single request, you could use this function to clean those up.
§Arguments
func- The function to be called when shutdown is requested.
Sourcepub fn sapi_activate_function<F>(self, callback: F) -> Self
pub fn sapi_activate_function<F>(self, callback: F) -> Self
Runs callback at the start of every request, with the request
information that the SAPI gives.
The callback runs from sapi_module.activate, after the SAPI handler.
Unlike the request startup function, it also runs for each request of a
FrankenPHP worker. At this point the response headers are empty, so
set_header and
set_response_code work. $_SERVER
does not exist yet and no PHP code can run.
A panic in callback is printed and ignored. A module loaded with
dl() refuses to start when it has this callback. Calling this method
again replaces the callback.
use ext_php_rs::prelude::*;
use ext_php_rs::zend::{SapiRequestInfo, set_header, set_response_code};
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module.sapi_activate_function(|info: &SapiRequestInfo| {
if info.request_uri() == Some("/old") {
let _ = set_header("Location: /new");
let _ = set_response_code(301);
}
})
}Sourcepub fn info_function(
self,
func: unsafe extern "C" fn(zend_module: *mut ModuleEntry),
) -> Self
pub fn info_function( self, func: unsafe extern "C" fn(zend_module: *mut ModuleEntry), ) -> Self
Sets the extension information function for the extension.
§Arguments
func- The function to be called to retrieve the information about the extension.
Sourcepub fn globals<T: ModuleGlobal>(self, handle: &'static ModuleGlobals<T>) -> Self
pub fn globals<T: ModuleGlobal>(self, handle: &'static ModuleGlobals<T>) -> Self
Registers a module globals struct with this extension.
PHP will allocate per-thread storage (ZTS) or use the static’s inline storage (non-ZTS), calling GINIT/GSHUTDOWN callbacks automatically.
Only one globals struct per module is supported (PHP limitation). Calling this a second time will overwrite the previous registration.
§Arguments
handle- A staticModuleGlobalsthat will hold the globals.
§Examples
use ext_php_rs::prelude::*;
use ext_php_rs::zend::{ModuleGlobal, ModuleGlobals};
#[derive(Default)]
struct MyGlobals { counter: i64 }
impl ModuleGlobal for MyGlobals {}
static MY_GLOBALS: ModuleGlobals<MyGlobals> = ModuleGlobals::new();
#[php_module]
pub fn module(module: ModuleBuilder) -> ModuleBuilder {
module.globals(&MY_GLOBALS)
}Sourcepub fn fcall_observer<F, O>(self, factory: F) -> Self
Available on crate feature observer only.
pub fn fcall_observer<F, O>(self, factory: F) -> Self
observer only.Registers a function call observer for profiling or tracing.
The factory function is called once, at the first MINIT, to create
a singleton observer instance shared across all requests and threads.
When the SAPI starts the module again in the same process, the hook is
registered again with the same instance.
The observer must be Send + Sync as it may be accessed concurrently
in ZTS builds.
§Arguments
factory- A function that creates an observer instance
§Example
use ext_php_rs::prelude::*;
use ext_php_rs::zend::{FcallObserver, FcallInfo, ExecuteData};
use ext_php_rs::types::Zval;
struct MyProfiler;
impl FcallObserver for MyProfiler {
fn should_observe(&self, info: &FcallInfo) -> bool {
!info.is_internal
}
fn begin(&self, _: &ExecuteData) {}
fn end(&self, _: &ExecuteData, _: Option<&Zval>) {}
}
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module.fcall_observer(|| MyProfiler)
}§Panics
Panics if called more than once on the same module.
Sourcepub fn error_observer<F, O>(self, factory: F) -> Self
Available on crate feature observer only.
pub fn error_observer<F, O>(self, factory: F) -> Self
observer only.Registers an error observer for monitoring PHP errors.
The factory function is called once, at the first MINIT, to create
a singleton observer instance shared across all requests.
When the SAPI starts the module again in the same process, the hook is
registered again with the same instance.
The observer must be Send + Sync for ZTS builds.
§Arguments
factory- A function that creates an observer instance
§Example
use ext_php_rs::prelude::*;
struct MyErrorLogger;
impl ErrorObserver for MyErrorLogger {
fn should_observe(&self, error_type: ErrorType) -> bool {
ErrorType::Fatal.contains(error_type)
}
fn on_error(&self, error: &ErrorInfo) {
eprintln!("[{}:{}] {}",
error.filename.unwrap_or("<unknown>"),
error.lineno,
error.message
);
}
}
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module.error_observer(MyErrorLogger)
}§Panics
Panics if called more than once on the same module.
Sourcepub fn exception_observer<F, O>(self, factory: F) -> Self
Available on crate feature observer only.
pub fn exception_observer<F, O>(self, factory: F) -> Self
observer only.Registers an exception observer for monitoring thrown PHP exceptions.
The factory function is called once, at the first MINIT, to create
a singleton observer instance shared across all requests.
When the SAPI starts the module again in the same process, the hook is
registered again with the same instance.
The observer must be Send + Sync for ZTS builds.
The observer is called at throw time, before any catch blocks are evaluated.
§Arguments
factory- A function that creates an observer instance
§Example
use ext_php_rs::prelude::*;
struct MyExceptionLogger;
impl ExceptionObserver for MyExceptionLogger {
fn on_exception(&self, exception: &ExceptionInfo) {
eprintln!("[EXCEPTION] {}: {} at {}:{}",
exception.class_name,
exception.message.as_deref().unwrap_or("<no message>"),
exception.file.as_deref().unwrap_or("<unknown>"),
exception.line
);
}
}
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module.exception_observer(|| MyExceptionLogger)
}§Panics
Panics if called more than once on the same module.
Sourcepub fn function(self, func: FunctionBuilder<'static>) -> Self
pub fn function(self, func: FunctionBuilder<'static>) -> Self
Sourcepub fn constant(
self,
const: (&str, impl IntoConst + Send + 'static, DocComments),
) -> Self
pub fn constant( self, const: (&str, impl IntoConst + Send + 'static, DocComments), ) -> Self
Adds a constant to the extension.
§Arguments
const- Tuple containing the name, value and doc comments for the constant. This is a tuple to support thewrap_constantmacro.
Sourcepub fn interface<T: RegisteredClass>(self) -> Self
pub fn interface<T: RegisteredClass>(self) -> Self
Sourcepub fn class<T: RegisteredClass>(self) -> Self
pub fn class<T: RegisteredClass>(self) -> Self
Sourcepub fn enumeration<T>(self) -> Selfwhere
T: RegisteredClass + RegisteredEnum,
Available on crate feature enum only.
pub fn enumeration<T>(self) -> Selfwhere
T: RegisteredClass + RegisteredEnum,
enum only.Adds an enum to the extension.
Source§impl<'a> ModuleBuilder<'a>
impl<'a> ModuleBuilder<'a>
Sourcepub fn zend_extension<F, H>(self, factory: F) -> ZendExtensionBuilder<'a>
Available on crate feature observer only.
pub fn zend_extension<F, H>(self, factory: F) -> ZendExtensionBuilder<'a>
observer only.Register a ZendExtensionHandler and configure which hooks PHP should
call.
Returns a ZendExtensionBuilder that exposes three opt-in methods
(hook_statements, hook_fcalls, hook_op_array_compile). Call
ZendExtensionBuilder::finish to return to ModuleBuilder.
§Example
module
.zend_extension(|| MyProfiler::new())
.hook_statements()
.finish()§Panics
Panics if called more than once on the same module.
Trait Implementations§
Source§impl<'a> Debug for ModuleBuilder<'a>
impl<'a> Debug for ModuleBuilder<'a>
Source§impl Default for ModuleBuilder<'_>
impl Default for ModuleBuilder<'_>
Source§impl From<ModuleBuilder<'_>> for Module
Builds a Module from a ModuleBuilder.
This is used to generate the PHP stubs for the module.
impl From<ModuleBuilder<'_>> for Module
Builds a Module from a ModuleBuilder.
This is used to generate the PHP stubs for the module.
Source§fn from(builder: ModuleBuilder<'_>) -> Self
fn from(builder: ModuleBuilder<'_>) -> Self
Source§impl TryFrom<ModuleBuilder<'_>> for (ModuleEntry, ModuleStartup, ModuleAllocations)
Builds a ModuleEntry and ModuleStartup from a ModuleBuilder.
This is the entry point for the module to be registered with PHP.
impl TryFrom<ModuleBuilder<'_>> for (ModuleEntry, ModuleStartup, ModuleAllocations)
Builds a ModuleEntry and ModuleStartup from a ModuleBuilder.
This is the entry point for the module to be registered with PHP.