Skip to main content

ModuleBuilder

Struct ModuleBuilder 

Source
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<'_>

Source

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.
Source

pub fn name(self, name: impl Into<String>) -> Self

Overrides module name.

§Arguments
  • name - The name of the extension.
Source

pub fn version(self, version: impl Into<String>) -> Self

Overrides module version.

§Arguments
  • version - The current version of the extension.
Source

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.
Source

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.
Source

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.
Source

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.
Source

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.
Source

pub fn sapi_activate_function<F>(self, callback: F) -> Self
where F: Fn(&SapiRequestInfo) + Send + Sync + 'static,

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);
        }
    })
}
Source

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.
Source

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
§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)
}
Source

pub fn fcall_observer<F, O>(self, factory: F) -> Self
where F: Fn() -> O + Send + Sync + 'static, O: FcallObserver + Send + Sync,

Available on crate feature 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.

Source

pub fn error_observer<F, O>(self, factory: F) -> Self
where F: Fn() -> O + Send + Sync + 'static, O: ErrorObserver + Send + Sync,

Available on crate feature 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.

Source

pub fn exception_observer<F, O>(self, factory: F) -> Self
where F: Fn() -> O + Send + Sync + 'static, O: ExceptionObserver + Send + Sync,

Available on crate feature 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.

Source

pub fn function(self, func: FunctionBuilder<'static>) -> Self

Adds a function to the extension.

§Arguments
  • func - The function to be added to the extension.
Source

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 the wrap_constant macro.
Source

pub fn interface<T: RegisteredClass>(self) -> Self

Adds a interface to the extension.

§Panics
  • Panics if a constant could not be registered.
Source

pub fn class<T: RegisteredClass>(self) -> Self

Adds a class to the extension.

§Panics
  • Panics if a constant could not be registered.
Source

pub fn enumeration<T>(self) -> Self

Available on crate feature enum only.

Adds an enum to the extension.

Source§

impl<'a> ModuleBuilder<'a>

Source

pub fn zend_extension<F, H>(self, factory: F) -> ZendExtensionBuilder<'a>
where F: Fn() -> H + Send + Sync + 'static, H: ZendExtensionHandler,

Available on crate feature 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>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ModuleBuilder<'_>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

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

Converts to this type from the input type.
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.

Source§

type Error = Error

The type returned in the event of a conversion error.
Source§

fn try_from(builder: ModuleBuilder<'_>) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for ModuleBuilder<'a>

§

impl<'a> !Send for ModuleBuilder<'a>

§

impl<'a> !Sync for ModuleBuilder<'a>

§

impl<'a> !UnwindSafe for ModuleBuilder<'a>

§

impl<'a> Freeze for ModuleBuilder<'a>

§

impl<'a> Unpin for ModuleBuilder<'a>

§

impl<'a> UnsafeUnpin for ModuleBuilder<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.