Skip to content

Commit 660f652

Browse files
committed
Add enum
1 parent 2e8f3a3 commit 660f652

File tree

11 files changed

+503
-268
lines changed

11 files changed

+503
-268
lines changed
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Register Enums
2+
3+
> PHP 8.1 and above introduced the Enum functionality. `PHPER` allowing you to create PHP enums using Rust code.
4+
5+
In `PHPER`, you can use the [`add_enum`](phper::modules::Module::add_enum) method to register enums.
6+
According to PHP's enum specification, `PHPER` supports three types of enums:
7+
8+
1. Pure enums (without values)
9+
2. Integer-backed enums
10+
3. String-backed enums
11+
12+
## Creating Pure Enums
13+
14+
Pure enums are the simplest type of enum, having only member names without associated values. Use `EnumEntity<()>` to create a pure enum (or simply use `EnumEntity::new()` since `()` is the default type parameter).
15+
16+
```rust,no_run
17+
use phper::{modules::Module, php_get_module, enums::EnumEntity, classes::Visibility};
18+
19+
#[php_get_module]
20+
pub fn get_module() -> Module {
21+
let mut module = Module::new(
22+
env!("CARGO_CRATE_NAME"),
23+
env!("CARGO_PKG_VERSION"),
24+
env!("CARGO_PKG_AUTHORS"),
25+
);
26+
27+
// Create a pure enum
28+
let mut status = EnumEntity::new("Status");
29+
30+
// Add enum cases (without values)
31+
status.add_case("PENDING", ());
32+
status.add_case("ACTIVE", ());
33+
status.add_case("INACTIVE", ());
34+
35+
// Register the enum to the module
36+
module.add_enum(status);
37+
38+
module
39+
}
40+
```
41+
42+
This is equivalent to the following PHP code:
43+
44+
```php
45+
enum Status {
46+
case PENDING;
47+
case ACTIVE;
48+
case INACTIVE;
49+
}
50+
```
51+
52+
## Creating Integer-Backed Enums
53+
54+
Integer-backed enums associate each enum member with an integer value. Use `EnumEntity<i64>` to create an integer-backed enum.
55+
56+
```rust,no_run
57+
use phper::{modules::Module, php_get_module, enums::EnumEntity};
58+
59+
#[php_get_module]
60+
pub fn get_module() -> Module {
61+
let mut module = Module::new(
62+
env!("CARGO_CRATE_NAME"),
63+
env!("CARGO_PKG_VERSION"),
64+
env!("CARGO_PKG_AUTHORS"),
65+
);
66+
67+
// Create an integer-backed enum
68+
let mut level = EnumEntity::<i64>::new("Level");
69+
70+
// Add enum cases with their associated integer values
71+
level.add_case("LOW", 1);
72+
level.add_case("MEDIUM", 5);
73+
level.add_case("HIGH", 10);
74+
75+
// Register the enum to the module
76+
module.add_enum(level);
77+
78+
module
79+
}
80+
```
81+
82+
This is equivalent to the following PHP code:
83+
84+
```php
85+
enum Level: int {
86+
case LOW = 1;
87+
case MEDIUM = 5;
88+
case HIGH = 10;
89+
}
90+
```
91+
92+
## Creating String-Backed Enums
93+
94+
String-backed enums associate each enum member with a string value. Use `EnumEntity<String>` to create a string-backed enum.
95+
96+
```rust,no_run
97+
use phper::{modules::Module, php_get_module, enums::EnumEntity};
98+
99+
#[php_get_module]
100+
pub fn get_module() -> Module {
101+
let mut module = Module::new(
102+
env!("CARGO_CRATE_NAME"),
103+
env!("CARGO_PKG_VERSION"),
104+
env!("CARGO_PKG_AUTHORS"),
105+
);
106+
107+
// Create a string-backed enum
108+
let mut color = EnumEntity::<String>::new("Color");
109+
110+
// Add enum cases with their associated string values
111+
color.add_case("RED", "FF0000".to_string());
112+
color.add_case("GREEN", "00FF00".to_string());
113+
color.add_case("BLUE", "0000FF".to_string());
114+
115+
// Register the enum to the module
116+
module.add_enum(color);
117+
118+
module
119+
}
120+
```
121+
122+
This is equivalent to the following PHP code:
123+
124+
```php
125+
enum Color: string {
126+
case RED = "FF0000";
127+
case GREEN = "00FF00";
128+
case BLUE = "0000FF";
129+
}
130+
```
131+
132+
## Adding Constants
133+
134+
Enums can contain constants. Use the `add_constant` method to add constants to an enum.
135+
136+
```rust,no_run
137+
use phper::{modules::Module, php_get_module, enums::EnumEntity};
138+
139+
let mut status = EnumEntity::new("Status");
140+
141+
// Add enum cases
142+
status.add_case("PENDING", ());
143+
status.add_case("ACTIVE", ());
144+
145+
// Add constants
146+
status.add_constant("VERSION", "1.0.0");
147+
status.add_constant("MAX_ATTEMPTS", 3);
148+
```
149+
150+
This is equivalent to the following PHP code:
151+
152+
```php
153+
enum Status {
154+
case PENDING;
155+
case ACTIVE;
156+
157+
public const VERSION = "1.0.0";
158+
public const MAX_ATTEMPTS = 3;
159+
}
160+
```
161+
162+
## Adding Static Methods
163+
164+
You can add static methods to enums. Use the `add_static_method` method to add a static method to an enum.
165+
166+
```rust,no_run
167+
use phper::{modules::Module, php_get_module, enums::EnumEntity, classes::Visibility};
168+
use std::convert::Infallible;
169+
170+
let mut status = EnumEntity::new("Status");
171+
172+
// Add enum cases
173+
status.add_case("PENDING", ());
174+
status.add_case("ACTIVE", ());
175+
176+
// Add static method
177+
status.add_static_method("getDescription", Visibility::Public, |_| {
178+
Ok::<_, Infallible>("Status enumeration for tracking item states")
179+
});
180+
```
181+
182+
This is equivalent to the following PHP code:
183+
184+
```php
185+
enum Status {
186+
case PENDING;
187+
case ACTIVE;
188+
189+
public static function getDescription(): string {
190+
return "Status enumeration for tracking item states";
191+
}
192+
}
193+
```
194+
195+
## Implementing Interfaces
196+
197+
You can make enums implement interfaces. Use the `implements` method to make an enum implement a specific interface.
198+
199+
```rust,no_run
200+
use phper::{modules::Module, php_get_module, enums::EnumEntity, classes::Interface};
201+
202+
let mut color = EnumEntity::<String>::new("Color");
203+
204+
// Add enum cases
205+
color.add_case("RED", "FF0000".to_string());
206+
color.add_case("GREEN", "00FF00".to_string());
207+
208+
// Implement interface
209+
color.implements(Interface::from_name("JsonSerializable"));
210+
211+
// Note: You need to add necessary methods to satisfy interface requirements
212+
// For example, JsonSerializable interface requires the implementation of jsonSerialize method
213+
```
214+
215+
## Using Built-in Enum Methods
216+
217+
PHP enums come with some built-in methods. Pure enums (`UnitEnum`) have the `cases()` method, while backed enums (`BackedEnum`) additionally have the `from()` and `tryFrom()` methods.
218+
219+
```php
220+
// Examples of using built-in methods in PHP
221+
$allCases = Color::cases(); // Returns an array of all enum cases
222+
223+
// Only available for backed enums
224+
$colorFromValue = Color::from("FF0000"); // Returns RED
225+
$colorOrNull = Color::tryFrom("INVALID"); // Returns null (when the value doesn't exist)
226+
```
227+
228+
## Complete Example
229+
230+
Here's a comprehensive example using both pure and backed enums:
231+
232+
```rust,no_run
233+
use phper::{
234+
modules::Module,
235+
php_get_module,
236+
enums::EnumEntity,
237+
classes::Visibility
238+
};
239+
use std::convert::Infallible;
240+
241+
#[php_get_module]
242+
pub fn get_module() -> Module {
243+
let mut module = Module::new(
244+
env!("CARGO_CRATE_NAME"),
245+
env!("CARGO_PKG_VERSION"),
246+
env!("CARGO_PKG_AUTHORS"),
247+
);
248+
249+
// Pure enum
250+
let mut status = EnumEntity::new("Status");
251+
status.add_case("PENDING", ());
252+
status.add_case("ACTIVE", ());
253+
status.add_case("INACTIVE", ());
254+
status.add_constant("VERSION", "1.0.0");
255+
status.add_static_method("getDescription", Visibility::Public, |_| {
256+
Ok::<_, Infallible>("Status enumeration")
257+
});
258+
259+
// Integer-backed enum
260+
let mut level = EnumEntity::<i64>::new("Level");
261+
level.add_case("LOW", 1);
262+
level.add_case("MEDIUM", 5);
263+
level.add_case("HIGH", 10);
264+
265+
// Register enums to the module
266+
module.add_enum(status);
267+
module.add_enum(level);
268+
269+
module
270+
}
271+
```
272+
273+
> **Note**: PHP enums require PHP 8.1 or higher. Make sure your extension sets the correct PHP version requirements.

phper-doc/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ pub mod _06_module {
6969

7070
#[doc = include_str!("../doc/_06_module/_07_register_interface/index.md")]
7171
pub mod _07_register_interface {}
72+
73+
#[doc = include_str!("../doc/_06_module/_08_register_enum/index.md")]
74+
pub mod _08_register_enum {}
7275
}
7376

7477
/// TODO

phper/src/classes.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,14 +940,16 @@ impl ConstantEntity {
940940
}
941941

942942
/// Builder for declare class property.
943-
struct PropertyEntity {
943+
pub(crate) struct PropertyEntity {
944944
name: String,
945945
visibility: RawVisibility,
946946
value: Scalar,
947947
}
948948

949949
impl PropertyEntity {
950-
fn new(name: impl Into<String>, visibility: Visibility, value: impl Into<Scalar>) -> Self {
950+
pub(crate) fn new(
951+
name: impl Into<String>, visibility: Visibility, value: impl Into<Scalar>,
952+
) -> Self {
951953
Self {
952954
name: name.into(),
953955
visibility: visibility as RawVisibility,

0 commit comments

Comments
 (0)