Phper:使用纯正且安全的 Rust 语言编写 PHP 扩展

Php

编写你的第一个扩展

在这里,我们将编写一个 “Hello World” 扩展,它包含一个函数,接收人名并向此人输出问候语。

完整示例请访问:https://github.com/phper - framework/phper/tree/master/examples/hello 。

步骤

  1. 确保安装了libclang(bindgen所需)
    • phper require libclang 9.0+
    • 如果你使用的是类似Debian的Linux系统
      • sudo apt install llvm - 10 - dev libclang - 10 - dev
  2. 创建Cargo项目,并指定扩展名称
    • cargo new --lib hello
    • cd hello
  3. 在Cargo.toml中添加元数据以构建.so文件
    • Cargo.toml
[lib]
crate - type = ["cdylib"]
  1. 运行命令添加phper依赖
    • cargo add phper
  2. 创建build.rs(适配MacOS)
fn main() {
    #[cfg(target_os = "macos")]
    {
        println!("cargo:rustc - link - arg=-undefined");
        println!("cargo:rustc - link - arg=dynamic_lookup");
    }
}
  1. 将以下代码添加到src/lib.rs
use phper::{echo, functions::Argument, modules::Module, php_get_module, values::ZVal};

/// 这个PHP函数接收类型为`ZVal`的参数。
fn say_hello(arguments: &mut [ZVal]) -> phper::Result<()> {
    // 获取第一个参数,期望类型为`ZStr`,并转换为Rust的UTF - 8字符串。
    let name = arguments[0].expect_z_str()?.to_str()?;

    // 此宏用于执行PHP内部的`echo`操作。
    echo!("Hello, {}!\n", name);

    Ok(())
}

/// 这是PHP扩展的入口,`php_get_module`属性宏将生成`extern "C" fn`。
#[php_get_module]
pub fn get_module() -> Module {
    // 使用扩展信息新建`Module`。
    let mut module = Module::new(
        env!("CARGO_PKG_NAME"),
        env!("CARGO_PKG_VERSION"),
        env!("CARGO_PKG_AUTHORS"),
    );

    // 注册函数`say_hello`,该函数有一个参数`name`。
    module.add_function("say_hello", say_hello).argument(Argument::by_val("name"));

    module
}
  1. 构建:如果你的PHP没有全局安装,你应该指定php - config的路径。
    • 可选,若PHP未全局安装则指定路径:此环境变量由phper - sys使用。
    • export PHP_CONFIG=<你的php - config路径>
    • 构建libhello.socargo build
  2. 使用扩展运行PHP命令
    • php -d "extension = target/debug/libhello.so" -r "say_hello('Bob');"

然后你会得到输出:

Hello, Bob!
Publish on 2025-01-08,Update on 2025-02-10