Skip to content

Commit 11e0d20

Browse files
committed
docs(macro): update docs to outer macro pattern
Refs: #335
1 parent 04589f9 commit 11e0d20

32 files changed

+621
-1127
lines changed

README.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,19 @@ Export a simple function `function hello_world(string $name): string` to PHP:
1919
```rust
2020
#![cfg_attr(windows, feature(abi_vectorcall))]
2121

22-
use ext_php_rs::prelude::*;
23-
24-
/// Gives you a nice greeting!
25-
///
26-
/// @param string $name Your name.
27-
///
28-
/// @return string Nice greeting!
29-
#[php_function]
30-
pub fn hello_world(name: String) -> String {
31-
format!("Hello, {}!", name)
32-
}
22+
use ext_php_rs::php_module;
3323

34-
// Required to register the extension with PHP.
3524
#[php_module]
36-
pub fn module(module: ModuleBuilder) -> ModuleBuilder {
37-
module
25+
mod module {
26+
/// Gives you a nice greeting!
27+
///
28+
/// @param string $name Your name.
29+
///
30+
/// @return string Nice greeting!
31+
#[php_function]
32+
pub fn hello_world(name: String) -> String {
33+
format!("Hello, {}!", name)
34+
}
3835
}
3936
```
4037

crates/macros/src/module_builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ impl ModuleBuilder {
9292

9393
quote! {
9494
mod module {
95+
use ::ext_php_rs::prelude::*;
9596
#class_stream
9697
#(#impl_stream)*
9798
#(#registered_classes_impls)*

guide/src/exceptions.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,18 @@ the `#[php_function]` attribute.
3030
# #![cfg_attr(windows, feature(abi_vectorcall))]
3131
# extern crate ext_php_rs;
3232
use ext_php_rs::prelude::*;
33-
use std::convert::TryInto;
34-
35-
// Trivial example - PHP represents all integers as `u64` on 64-bit systems
36-
// so the `u32` would be converted back to `u64`, but that's okay for an example.
37-
#[php_function]
38-
pub fn something_fallible(n: u64) -> PhpResult<u32> {
39-
let n: u32 = n.try_into().map_err(|_| "Could not convert into u32")?;
40-
Ok(n)
41-
}
4233
4334
#[php_module]
44-
pub fn module(module: ModuleBuilder) -> ModuleBuilder {
45-
module
35+
mod module {
36+
use std::convert::TryInto;
37+
38+
// Trivial example - PHP represents all integers as `u64` on 64-bit systems
39+
// so the `u32` would be converted back to `u64`, but that's okay for an example.
40+
#[php_function]
41+
pub fn something_fallible(n: u64) -> PhpResult<u32> {
42+
let n: u32 = n.try_into().map_err(|_| "Could not convert into u32")?;
43+
Ok(n)
44+
}
4645
}
4746
# fn main() {}
4847
```

guide/src/ini-settings.md

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,23 @@ All PHP INI definitions must be registered with PHP to get / set their values vi
1111
# #![cfg_attr(windows, feature(abi_vectorcall))]
1212
# extern crate ext_php_rs;
1313
# use ext_php_rs::prelude::*;
14-
# use ext_php_rs::zend::IniEntryDef;
15-
# use ext_php_rs::flags::IniEntryPermission;
16-
17-
#[php_startup]
18-
pub fn startup_function(ty: i32, module_number: i32) {
19-
let ini_entries: Vec<IniEntryDef> = vec![
20-
IniEntryDef::new(
21-
"my_extension.display_emoji".to_owned(),
22-
"yes".to_owned(),
23-
IniEntryPermission::All,
24-
),
25-
];
26-
IniEntryDef::register(ini_entries, module_number);
14+
15+
#[php_module]
16+
mod module {
17+
# use ext_php_rs::zend::IniEntryDef;
18+
# use ext_php_rs::flags::IniEntryPermission;
19+
20+
#[php_startup]
21+
pub fn startup_function(ty: i32, module_number: i32) {
22+
let ini_entries: Vec<IniEntryDef> = vec![
23+
IniEntryDef::new(
24+
"my_extension.display_emoji".to_owned(),
25+
"yes".to_owned(),
26+
IniEntryPermission::All,
27+
),
28+
];
29+
IniEntryDef::register(ini_entries, module_number);
30+
}
2731
}
2832
# fn main() {}
2933
```
@@ -36,13 +40,16 @@ The INI values are stored as part of the `GlobalExecutor`, and can be accessed v
3640
# #![cfg_attr(windows, feature(abi_vectorcall))]
3741
# extern crate ext_php_rs;
3842
# use ext_php_rs::prelude::*;
39-
# use ext_php_rs::zend::ExecutorGlobals;
4043
41-
#[php_startup]
42-
pub fn startup_function(ty: i32, module_number: i32) {
43-
// Get all INI values
44-
let ini_values = ExecutorGlobals::get().ini_values(); // HashMap<String, Option<String>>
45-
let my_ini_value = ini_values.get("my_extension.display_emoji"); // Option<Option<String>>
44+
#[php_module]
45+
mod module {
46+
# use ext_php_rs::zend::ExecutorGlobals;
47+
#[php_startup]
48+
pub fn startup_function(ty: i32, module_number: i32) {
49+
// Get all INI values
50+
let ini_values = ExecutorGlobals::get().ini_values(); // HashMap<String, Option<String>>
51+
let my_ini_value = ini_values.get("my_extension.display_emoji"); // Option<Option<String>>
52+
}
4653
}
4754
# fn main() {}
4855
```

guide/src/macros/classes.md

Lines changed: 66 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
Structs can be exported to PHP as classes with the `#[php_class]` attribute
44
macro. This attribute derives the `RegisteredClass` trait on your struct, as
5-
well as registering the class to be registered with the `#[php_module]` macro.
5+
well as registering the class to be registered with the `#[php_module]` containing
6+
the class.
67

78
## Options
89

@@ -12,8 +13,7 @@ The attribute takes some options to modify the output of the class:
1213
name is kept the same. If no name is given, the name of the struct is used.
1314
Useful for namespacing classes.
1415

15-
There are also additional macros that modify the class. These macros **must** be
16-
placed underneath the `#[php_class]` attribute.
16+
There are also additional macros that modify the class.
1717

1818
- `#[extends(ce)]` - Sets the parent class of the class. Can only be used once.
1919
`ce` must be a valid Rust expression when it is called inside the
@@ -23,7 +23,7 @@ placed underneath the `#[php_class]` attribute.
2323
the `#[php_module]` function.
2424

2525
You may also use the `#[prop]` attribute on a struct field to use the field as a
26-
PHP property. By default, the field will be accessible from PHP publicly with
26+
PHP property. By default, the field will then be accessible from PHP publicly with
2727
the same name as the field. Property types must implement `IntoZval` and
2828
`FromZval`.
2929

@@ -68,17 +68,16 @@ This example creates a PHP class `Human`, adding a PHP property `address`.
6868
# #![cfg_attr(windows, feature(abi_vectorcall))]
6969
# extern crate ext_php_rs;
7070
# use ext_php_rs::prelude::*;
71-
#[php_class]
72-
pub struct Human {
73-
name: String,
74-
age: i32,
75-
#[prop]
76-
address: String,
71+
#[php_module]
72+
mod module {
73+
#[php_class]
74+
pub struct Human {
75+
name: String,
76+
age: i32,
77+
#[prop]
78+
address: String,
79+
}
7780
}
78-
# #[php_module]
79-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
80-
# module
81-
# }
8281
# fn main() {}
8382
```
8483

@@ -89,22 +88,22 @@ it in the `Redis\Exception` namespace:
8988
# #![cfg_attr(windows, feature(abi_vectorcall))]
9089
# extern crate ext_php_rs;
9190
use ext_php_rs::prelude::*;
92-
use ext_php_rs::{exception::PhpException, zend::ce};
9391
94-
#[php_class(name = "Redis\\Exception\\RedisException")]
95-
#[extends(ce::exception())]
96-
#[derive(Default)]
97-
pub struct RedisException;
92+
#[php_module]
93+
pub mod module {
94+
use ext_php_rs::{exception::PhpException, zend::ce};
95+
96+
#[php_class(name = "Redis\\Exception\\RedisException")]
97+
#[extends(ce::exception())]
98+
#[derive(Default)]
99+
pub struct RedisException;
98100
99-
// Throw our newly created exception
100-
#[php_function]
101-
pub fn throw_exception() -> PhpResult<i32> {
102-
Err(PhpException::from_class::<RedisException>("Not good!".into()))
101+
// Throw our newly created exception
102+
#[php_function]
103+
pub fn throw_exception() -> PhpResult<i32> {
104+
Err(PhpException::from_class::<RedisException>("Not good!".into()))
105+
}
103106
}
104-
# #[php_module]
105-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
106-
# module
107-
# }
108107
# fn main() {}
109108
```
110109

@@ -116,47 +115,47 @@ The following example implements [`ArrayAccess`](https://www.php.net/manual/en/c
116115
# #![cfg_attr(windows, feature(abi_vectorcall))]
117116
# extern crate ext_php_rs;
118117
use ext_php_rs::prelude::*;
119-
use ext_php_rs::{exception::PhpResult, types::Zval, zend::ce};
120-
121-
#[php_class]
122-
#[implements(ce::arrayaccess())]
123-
#[derive(Default)]
124-
pub struct EvenNumbersArray;
125-
126-
/// Returns `true` if the array offset is an even number.
127-
/// Usage:
128-
/// ```php
129-
/// $arr = new EvenNumbersArray();
130-
/// var_dump($arr[0]); // true
131-
/// var_dump($arr[1]); // false
132-
/// var_dump($arr[2]); // true
133-
/// var_dump($arr[3]); // false
134-
/// var_dump($arr[4]); // true
135-
/// var_dump($arr[5] = true); // Fatal error: Uncaught Exception: Setting values is not supported
136-
/// ```
137-
#[php_impl]
138-
impl EvenNumbersArray {
139-
pub fn __construct() -> EvenNumbersArray {
140-
EvenNumbersArray {}
141-
}
142-
// We need to use `Zval` because ArrayAccess needs $offset to be a `mixed`
143-
pub fn offset_exists(&self, offset: &'_ Zval) -> bool {
144-
offset.is_long()
145-
}
146-
pub fn offset_get(&self, offset: &'_ Zval) -> PhpResult<bool> {
147-
let integer_offset = offset.long().ok_or("Expected integer offset")?;
148-
Ok(integer_offset % 2 == 0)
149-
}
150-
pub fn offset_set(&mut self, _offset: &'_ Zval, _value: &'_ Zval) -> PhpResult {
151-
Err("Setting values is not supported".into())
152-
}
153-
pub fn offset_unset(&mut self, _offset: &'_ Zval) -> PhpResult {
154-
Err("Setting values is not supported".into())
118+
119+
#[php_module]
120+
mod module {
121+
use ext_php_rs::{exception::PhpResult, types::Zval, zend::ce};
122+
123+
#[php_class]
124+
#[implements(ce::arrayaccess())]
125+
#[derive(Default)]
126+
pub struct EvenNumbersArray;
127+
128+
/// Returns `true` if the array offset is an even number.
129+
/// Usage:
130+
/// ```php
131+
/// $arr = new EvenNumbersArray();
132+
/// var_dump($arr[0]); // true
133+
/// var_dump($arr[1]); // false
134+
/// var_dump($arr[2]); // true
135+
/// var_dump($arr[3]); // false
136+
/// var_dump($arr[4]); // true
137+
/// var_dump($arr[5] = true); // Fatal error: Uncaught Exception: Setting values is not supported
138+
/// ```
139+
#[php_impl]
140+
impl EvenNumbersArray {
141+
pub fn __construct() -> EvenNumbersArray {
142+
EvenNumbersArray {}
143+
}
144+
// We need to use `Zval` because ArrayAccess needs $offset to be a `mixed`
145+
pub fn offset_exists(&self, offset: &'_ Zval) -> bool {
146+
offset.is_long()
147+
}
148+
pub fn offset_get(&self, offset: &'_ Zval) -> PhpResult<bool> {
149+
let integer_offset = offset.long().ok_or("Expected integer offset")?;
150+
Ok(integer_offset % 2 == 0)
151+
}
152+
pub fn offset_set(&mut self, _offset: &'_ Zval, _value: &'_ Zval) -> PhpResult {
153+
Err("Setting values is not supported".into())
154+
}
155+
pub fn offset_unset(&mut self, _offset: &'_ Zval) -> PhpResult {
156+
Err("Setting values is not supported".into())
157+
}
155158
}
156159
}
157-
# #[php_module]
158-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
159-
# module
160-
# }
161160
# fn main() {}
162161
```

guide/src/macros/constant.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ that implements `IntoConst`.
99
# #![cfg_attr(windows, feature(abi_vectorcall))]
1010
# extern crate ext_php_rs;
1111
# use ext_php_rs::prelude::*;
12-
#[php_const]
13-
const TEST_CONSTANT: i32 = 100;
12+
#[php_module]
13+
mod module {
14+
#[php_const]
15+
const TEST_CONSTANT: i32 = 100;
1416
15-
#[php_const]
16-
const ANOTHER_STRING_CONST: &'static str = "Hello world!";
17-
# #[php_module]
18-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { module }
17+
#[php_const]
18+
const ANOTHER_STRING_CONST: &'static str = "Hello world!";
19+
}
1920
# fn main() {}
2021
```
2122

guide/src/macros/extern.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# `#[php_extern]`
2+
3+
Attribute used to annotate `extern` blocks which are deemed as PHP
4+
functions.
5+
6+
This allows you to 'import' PHP functions into Rust so that they can be
7+
called like regular Rust functions. Parameters can be any type that
8+
implements [`IntoZval`], and the return type can be anything that implements
9+
[`From<Zval>`] (notice how [`Zval`] is consumed rather than borrowed in this
10+
case).
11+
12+
Unlike most other attributes, this does not need to be placed inside a
13+
`#[php_module]` block.
14+
15+
# Panics
16+
17+
The function can panic when called under a few circumstances:
18+
19+
* The function could not be found or was not callable.
20+
* One of the parameters could not be converted into a [`Zval`].
21+
* The actual function call failed internally.
22+
* The output [`Zval`] could not be parsed into the output type.
23+
24+
The last point can be important when interacting with functions that return
25+
unions, such as [`strpos`] which can return an integer or a boolean. In this
26+
case, a [`Zval`] should be returned as parsing a boolean to an integer is
27+
invalid, and vice versa.
28+
29+
# Example
30+
31+
This `extern` block imports the [`strpos`] function from PHP. Notice that
32+
the string parameters can take either [`String`] or [`&str`], the optional
33+
parameter `offset` is an [`Option<i64>`], and the return value is a [`Zval`]
34+
as the return type is an integer-boolean union.
35+
36+
```rust,no_run
37+
# #![cfg_attr(windows, feature(abi_vectorcall))]
38+
# extern crate ext_php_rs;
39+
# use ext_php_rs::prelude::*;
40+
# use ext_php_rs::types::Zval;
41+
#[php_extern]
42+
extern "C" {
43+
fn strpos(haystack: &str, needle: &str, offset: Option<i64>) -> Zval;
44+
}
45+
46+
#[php_module]
47+
mod module {
48+
# use ext_php_rs::types::Zval;
49+
use super::strpos;
50+
51+
#[php_function]
52+
pub fn my_strpos() {
53+
assert_eq!(unsafe { strpos("Hello", "e", None) }.long(), Some(1));
54+
}
55+
}
56+
# fn main() {}
57+
```
58+
59+
[`strpos`]: https://www.php.net/manual/en/function.strpos.php
60+
[`IntoZval`]: crate::convert::IntoZval
61+
[`Zval`]: crate::types::Zval

0 commit comments

Comments
 (0)