Skip to content

Commit ab0bbe9

Browse files
davidcole1340ptondereau
authored andcommitted
documentation
1 parent ee45551 commit ab0bbe9

File tree

17 files changed

+178
-114
lines changed

17 files changed

+178
-114
lines changed

NEW_MACROS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ need to register the classes with the module builder:
3737
use ext_php_rs::prelude::*;
3838

3939
#[php_class]
40+
#[derive(Debug)]
4041
pub struct TestClass {
4142
#[prop]
4243
a: i32,
@@ -63,6 +64,12 @@ impl TestClass {
6364
fn x(&self) -> i32 {
6465
5
6566
}
67+
68+
pub fn builder_pattern(
69+
self_: &mut ZendClassObject<TestClass>,
70+
) -> &mut ZendClassObject<TestClass> {
71+
dbg!(self_)
72+
}
6673
}
6774

6875
#[php_module]

crates/macros/src/class.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,19 @@ fn generate_registered_class_impl(
181181
fn method_builders() -> ::std::vec::Vec<
182182
(::ext_php_rs::builders::FunctionBuilder<'static>, ::ext_php_rs::flags::MethodFlags)
183183
> {
184+
use ::ext_php_rs::internal::class::PhpClassImpl;
184185
::ext_php_rs::internal::class::PhpClassImplCollector::<Self>::default().get_methods()
185186
}
186187

187188
#[inline]
188189
fn constructor() -> ::std::option::Option<::ext_php_rs::class::ConstructorMeta<Self>> {
190+
use ::ext_php_rs::internal::class::PhpClassImpl;
189191
::ext_php_rs::internal::class::PhpClassImplCollector::<Self>::default().get_constructor()
190192
}
191193

192194
#[inline]
193195
fn constants() -> &'static [(&'static str, &'static dyn ::ext_php_rs::convert::IntoZvalDyn)] {
196+
use ::ext_php_rs::internal::class::PhpClassImpl;
194197
::ext_php_rs::internal::class::PhpClassImplCollector::<Self>::default().get_constants()
195198
}
196199
}

crates/macros/src/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ impl<'a> TypedArg<'a> {
454454
}
455455
});
456456
Ok(quote! {
457-
::ext_php_rs::args::Arg::new(#name, <#ty as ::ext_php_rs::convert::FromZval>::TYPE)
457+
::ext_php_rs::args::Arg::new(#name, <#ty as ::ext_php_rs::convert::FromZvalMut>::TYPE)
458458
#null
459459
#default
460460
})
@@ -465,7 +465,7 @@ impl<'a> TypedArg<'a> {
465465
let name = self.name;
466466
if let Some(default) = &self.default {
467467
quote! {
468-
#name.val().unwrap_or(#default)
468+
#name.val().unwrap_or(#default.into())
469469
}
470470
} else if self.nullable {
471471
// Originally I thought we could just use the below case for `null` options, as

crates/macros/src/impl_.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,36 @@ impl<'a> ParsedImpl<'a> {
266266
opts.parse(&mut method.attrs)?;
267267

268268
let args = Args::parse_from_fnargs(method.sig.inputs.iter(), opts.defaults)?;
269-
let func = Function::parse(&method.sig, Some(opts.name), args, opts.optional)?;
269+
let mut func =
270+
Function::parse(&method.sig, Some(opts.name), args, opts.optional)?;
270271

271272
if matches!(opts.ty, MethodTy::Constructor) {
272273
if self.constructor.replace(func).is_some() {
273274
bail!(method => "Only one constructor can be provided per class.");
274275
}
275276
} else {
276-
let builder = func.function_builder(CallType::Method {
277+
let call_type = CallType::Method {
277278
class: self.path,
278279
receiver: if func.args.receiver.is_some() {
280+
// `&self` or `&mut self`
279281
MethodReceiver::Class
282+
} else if func
283+
.args
284+
.typed
285+
.first()
286+
.map(|arg| arg.name == "self_")
287+
.unwrap_or_default()
288+
{
289+
// `self_: &[mut] ZendClassObject<Self>`
290+
// Need to remove arg from argument list
291+
func.args.typed.pop();
292+
MethodReceiver::ZendClassObject
280293
} else {
294+
// Static method
281295
MethodReceiver::Static
282296
},
283-
})?;
297+
};
298+
let builder = func.function_builder(call_type)?;
284299
self.functions.push(FnBuilder {
285300
builder,
286301
vis: opts.vis,

crates/macros/src/zval.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ fn parse_enum(
235235
Ok(quote! {
236236
impl #into_impl_generics ::ext_php_rs::convert::IntoZval for #ident #ty_generics #into_where_clause {
237237
const TYPE: ::ext_php_rs::flags::DataType = ::ext_php_rs::flags::DataType::Mixed;
238+
const NULLABLE: bool = false;
238239

239240
fn set_zval(
240241
self,

examples/hello_world.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use ext_php_rs::{
77
flags::DataType,
88
internal::class::{PhpClassImpl, PhpClassImplCollector},
99
prelude::*,
10-
types::Zval,
10+
types::{ZendClassObject, Zval},
1111
zend::ExecuteData,
1212
};
1313

14+
#[derive(Debug)]
1415
#[php_class]
1516
pub struct TestClass {
1617
#[prop]
@@ -41,6 +42,12 @@ impl TestClass {
4142
fn x(&self) -> i32 {
4243
5
4344
}
45+
46+
pub fn builder_pattern(
47+
self_: &mut ZendClassObject<TestClass>,
48+
) -> &mut ZendClassObject<TestClass> {
49+
dbg!(self_)
50+
}
4451
}
4552

4653
#[php_function]

guide/src/SUMMARY.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
- [Async futures](./macros/impl.md#async)
2828
- [Macros](./macros/index.md)
2929
- [Module](./macros/module.md)
30-
- [Module Startup Function](./macros/module_startup.md)
3130
- [Function](./macros/function.md)
3231
- [Classes](./macros/classes.md)
3332
- [`impl`s](./macros/impl.md)

guide/src/macros/classes.md

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ There are also additional macros that modify the class. These macros **must** be
1616
placed underneath the `#[php_class]` attribute.
1717

1818
- `#[extends(ce)]` - Sets the parent class of the class. Can only be used once.
19-
`ce` must be a valid Rust expression when it is called inside the
20-
`#[php_module]` function.
19+
`ce` must be a function with the signature `fn() -> &'static ClassEntry`.
2120
- `#[implements(ce)]` - Implements the given interface on the class. Can be used
22-
multiple times. `ce` must be a valid Rust expression when it is called inside
23-
the `#[php_module]` function.
21+
multiple times. `ce` must be a function with the signature
22+
`fn() -> &'static ClassEntry`.
2423

2524
You may also use the `#[prop]` attribute on a struct field to use the field as a
2625
PHP property. By default, the field will be accessible from PHP publicly with
@@ -67,18 +66,20 @@ This example creates a PHP class `Human`, adding a PHP property `address`.
6766
```rust,no_run
6867
# #![cfg_attr(windows, feature(abi_vectorcall))]
6968
# extern crate ext_php_rs;
70-
# use ext_php_rs::prelude::*;
69+
use ext_php_rs::prelude::*;
70+
7171
#[php_class]
7272
pub struct Human {
7373
name: String,
7474
age: i32,
7575
#[prop]
7676
address: String,
7777
}
78-
# #[php_module]
79-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
80-
# module
81-
# }
78+
79+
#[php_module]
80+
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
81+
module.class::<Human>()
82+
}
8283
# fn main() {}
8384
```
8485

@@ -88,11 +89,14 @@ it in the `Redis\Exception` namespace:
8889
```rust,no_run
8990
# #![cfg_attr(windows, feature(abi_vectorcall))]
9091
# extern crate ext_php_rs;
91-
use ext_php_rs::prelude::*;
92-
use ext_php_rs::{exception::PhpException, zend::ce};
92+
use ext_php_rs::{
93+
prelude::*,
94+
exception::PhpException,
95+
zend::ce,
96+
};
9397
9498
#[php_class(name = "Redis\\Exception\\RedisException")]
95-
#[extends(ce::exception())]
99+
#[extends(ce::exception)]
96100
#[derive(Default)]
97101
pub struct RedisException;
98102
@@ -101,25 +105,33 @@ pub struct RedisException;
101105
pub fn throw_exception() -> PhpResult<i32> {
102106
Err(PhpException::from_class::<RedisException>("Not good!".into()))
103107
}
104-
# #[php_module]
105-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
106-
# module
107-
# }
108+
109+
#[php_module]
110+
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
111+
module
112+
.class::<RedisException>()
113+
.function(wrap_function!(throw_exception))
114+
}
108115
# fn main() {}
109116
```
110117

111118
## Implementing an Interface
112119

113-
To implement an interface, use `#[implements(ce)]` where `ce` is an expression returning a `ClassEntry`.
120+
To implement an interface, use `#[implements(ce)]` where `ce` is a function returning a `ClassEntry`.
114121
The following example implements [`ArrayAccess`](https://www.php.net/manual/en/class.arrayaccess.php):
122+
115123
```rust,no_run
116124
# #![cfg_attr(windows, feature(abi_vectorcall))]
117125
# extern crate ext_php_rs;
118-
use ext_php_rs::prelude::*;
119-
use ext_php_rs::{exception::PhpResult, types::Zval, zend::ce};
126+
use ext_php_rs::{
127+
prelude::*,
128+
exception::PhpResult,
129+
types::Zval,
130+
zend::ce,
131+
};
120132
121133
#[php_class]
122-
#[implements(ce::arrayaccess())]
134+
#[implements(ce::arrayaccess)]
123135
#[derive(Default)]
124136
pub struct EvenNumbersArray;
125137
@@ -154,9 +166,10 @@ impl EvenNumbersArray {
154166
Err("Setting values is not supported".into())
155167
}
156168
}
157-
# #[php_module]
158-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
159-
# module
160-
# }
169+
170+
#[php_module]
171+
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
172+
module.class::<EvenNumbersArray>()
173+
}
161174
# fn main() {}
162175
```

guide/src/macros/constant.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# `#[php_const]`
1+
# `wrap_constant!()`
22

33
Exports a Rust constant as a global PHP constant. The constant can be any type
44
that implements `IntoConst`.
@@ -8,14 +8,17 @@ that implements `IntoConst`.
88
```rust,no_run
99
# #![cfg_attr(windows, feature(abi_vectorcall))]
1010
# extern crate ext_php_rs;
11-
# use ext_php_rs::prelude::*;
12-
#[php_const]
13-
const TEST_CONSTANT: i32 = 100;
11+
use ext_php_rs::prelude::*;
1412
15-
#[php_const]
13+
const TEST_CONSTANT: i32 = 100;
1614
const ANOTHER_STRING_CONST: &'static str = "Hello world!";
17-
# #[php_module]
18-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { module }
15+
16+
#[php_module]
17+
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
18+
module
19+
.constant(wrap_constant!(TEST_CONSTANT))
20+
.constant(wrap_constant!(ANOTHER_STRING_CONST))
21+
}
1922
# fn main() {}
2023
```
2124

guide/src/macros/impl.md

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
You can export an entire `impl` block to PHP. This exports all methods as well
44
as constants to PHP on the class that it is implemented on. This requires the
55
`#[php_class]` macro to already be used on the underlying struct. Trait
6-
implementations cannot be exported to PHP.
6+
implementations cannot be exported to PHP. Only one `impl` block can be exported
7+
per class.
78

89
If you do not want a function exported to PHP, you should place it in a separate
910
`impl` block.
@@ -20,9 +21,8 @@ Class methods can take a `&self` or `&mut self` parameter. They cannot take a
2021
consuming `self` parameter. Static methods can omit this `self` parameter.
2122

2223
To access the underlying Zend object, you can take a reference to a
23-
`ZendClassObject<T>` in place of the self parameter, where the parameter is
24-
annotated with the `#[this]` attribute. This can also be used to return a
25-
reference to `$this`.
24+
`ZendClassObject<T>` in place of the self parameter, where the parameter must
25+
be named `self_`. This can also be used to return a reference to `$this`.
2626

2727
By default, all methods are renamed in PHP to the camel-case variant of the Rust
2828
method name. This can be changed on the `#[php_impl]` attribute, by passing one
@@ -114,22 +114,28 @@ constant for the maximum age of a `Human`.
114114
```rust,no_run
115115
# #![cfg_attr(windows, feature(abi_vectorcall))]
116116
# extern crate ext_php_rs;
117-
# use ext_php_rs::{prelude::*, types::ZendClassObject};
118-
# #[php_class]
119-
# #[derive(Debug, Default)]
120-
# pub struct Human {
121-
# name: String,
122-
# age: i32,
123-
# #[prop]
124-
# address: String,
125-
# }
117+
use ext_php_rs::{prelude::*, types::ZendClassObject};
118+
119+
#[php_class]
120+
#[derive(Debug, Default)]
121+
pub struct Human {
122+
name: String,
123+
age: i32,
124+
#[prop]
125+
address: String,
126+
}
127+
126128
#[php_impl]
127129
impl Human {
128130
const MAX_AGE: i32 = 100;
129131
130132
// No `#[constructor]` attribute required here - the name is `__construct`.
131133
pub fn __construct(name: String, age: i32) -> Self {
132-
Self { name, age, address: String::new() }
134+
Self {
135+
name,
136+
age,
137+
address: String::new(),
138+
}
133139
}
134140
135141
#[getter]
@@ -148,21 +154,25 @@ impl Human {
148154
}
149155
150156
pub fn introduce(&self) {
151-
println!("My name is {} and I am {} years old. I live at {}.", self.name, self.age, self.address);
157+
println!(
158+
"My name is {} and I am {} years old. I live at {}.",
159+
self.name, self.age, self.address
160+
);
152161
}
153162
154-
pub fn get_raw_obj(#[this] this: &mut ZendClassObject<Human>) {
155-
dbg!(this);
163+
pub fn get_raw_obj(self_: &mut ZendClassObject<Human>) -> &mut ZendClassObject<Human> {
164+
dbg!(self_)
156165
}
157166
158167
pub fn get_max_age() -> i32 {
159168
Self::MAX_AGE
160169
}
161170
}
162-
# #[php_module]
163-
# pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
164-
# module
165-
# }
171+
172+
#[php_module]
173+
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
174+
module.class::<Human>()
175+
}
166176
# fn main() {}
167177
```
168178

0 commit comments

Comments
 (0)