Skip to content

Commit 80a62d7

Browse files
committed
docs(superglobals): a guide chapter on Superglobals #499
1 parent b4d16f7 commit 80a62d7

File tree

2 files changed

+338
-0
lines changed

2 files changed

+338
-0
lines changed

guide/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
- [`Attributes`](./macros/php.md)
3737
- [Exceptions](./exceptions.md)
3838
- [INI Settings](./ini-settings.md)
39+
- [Superglobals](./superglobals.md)
3940

4041
# Advanced Topics
4142

guide/src/superglobals.md

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
# Superglobals
2+
3+
PHP provides several superglobal arrays that are accessible from any scope. In
4+
ext-php-rs, you can access these superglobals using the `ProcessGlobals`,
5+
`SapiGlobals`, and `ExecutorGlobals` types.
6+
7+
## Accessing HTTP Superglobals
8+
9+
The `ProcessGlobals` type provides access to the common HTTP superglobals:
10+
11+
| Method | PHP Equivalent |
12+
|-----------------------|----------------|
13+
| `http_get_vars()` | `$_GET` |
14+
| `http_post_vars()` | `$_POST` |
15+
| `http_cookie_vars()` | `$_COOKIE` |
16+
| `http_server_vars()` | `$_SERVER` |
17+
| `http_env_vars()` | `$_ENV` |
18+
| `http_files_vars()` | `$_FILES` |
19+
| `http_request_vars()` | `$_REQUEST` |
20+
21+
### Basic Example
22+
23+
```rust,no_run
24+
# #![cfg_attr(windows, feature(abi_vectorcall))]
25+
# extern crate ext_php_rs;
26+
use ext_php_rs::prelude::*;
27+
use ext_php_rs::zend::ProcessGlobals;
28+
29+
#[php_function]
30+
pub fn get_cookie(name: String) -> Option<String> {
31+
ProcessGlobals::get()
32+
.http_cookie_vars()
33+
.get(name.as_str())
34+
.and_then(|zval| zval.string())
35+
}
36+
37+
#[php_function]
38+
pub fn get_query_param(name: String) -> Option<String> {
39+
ProcessGlobals::get()
40+
.http_get_vars()
41+
.get(name.as_str())
42+
.and_then(|zval| zval.string())
43+
}
44+
45+
#[php_function]
46+
pub fn get_post_param(name: String) -> Option<String> {
47+
ProcessGlobals::get()
48+
.http_post_vars()
49+
.get(name.as_str())
50+
.and_then(|zval| zval.string())
51+
}
52+
# fn main() {}
53+
```
54+
55+
### Accessing `$_SERVER`
56+
57+
The `$_SERVER` superglobal is lazy-initialized in PHP, so `http_server_vars()`
58+
returns an `Option`:
59+
60+
```rust,no_run
61+
# #![cfg_attr(windows, feature(abi_vectorcall))]
62+
# extern crate ext_php_rs;
63+
use ext_php_rs::prelude::*;
64+
use ext_php_rs::zend::ProcessGlobals;
65+
66+
#[php_function]
67+
pub fn get_request_method() -> Option<String> {
68+
ProcessGlobals::get()
69+
.http_server_vars()?
70+
.get("REQUEST_METHOD")
71+
.and_then(|zval| zval.string())
72+
}
73+
74+
#[php_function]
75+
pub fn get_remote_addr() -> Option<String> {
76+
ProcessGlobals::get()
77+
.http_server_vars()?
78+
.get("REMOTE_ADDR")
79+
.and_then(|zval| zval.string())
80+
}
81+
82+
#[php_function]
83+
pub fn get_user_agent() -> Option<String> {
84+
ProcessGlobals::get()
85+
.http_server_vars()?
86+
.get("HTTP_USER_AGENT")
87+
.and_then(|zval| zval.string())
88+
}
89+
# fn main() {}
90+
```
91+
92+
### Working with `$_FILES`
93+
94+
```rust,no_run
95+
# #![cfg_attr(windows, feature(abi_vectorcall))]
96+
# extern crate ext_php_rs;
97+
use ext_php_rs::prelude::*;
98+
use ext_php_rs::zend::ProcessGlobals;
99+
100+
#[php_function]
101+
pub fn get_uploaded_file_name(field: String) -> Option<String> {
102+
let globals = ProcessGlobals::get();
103+
let files = globals.http_files_vars();
104+
105+
// $_FILES structure: $_FILES['field']['name'], ['tmp_name'], ['size'], etc.
106+
files
107+
.get(field.as_str())?
108+
.array()?
109+
.get("name")
110+
.and_then(|zval| zval.string())
111+
}
112+
113+
#[php_function]
114+
pub fn get_uploaded_file_tmp_path(field: String) -> Option<String> {
115+
let globals = ProcessGlobals::get();
116+
let files = globals.http_files_vars();
117+
118+
files
119+
.get(field.as_str())?
120+
.array()?
121+
.get("tmp_name")
122+
.and_then(|zval| zval.string())
123+
}
124+
# fn main() {}
125+
```
126+
127+
### Returning Superglobals to PHP
128+
129+
You can return copies of superglobals back to PHP:
130+
131+
```rust,no_run
132+
# #![cfg_attr(windows, feature(abi_vectorcall))]
133+
# extern crate ext_php_rs;
134+
use ext_php_rs::prelude::*;
135+
use ext_php_rs::boxed::ZBox;
136+
use ext_php_rs::types::ZendHashTable;
137+
use ext_php_rs::zend::ProcessGlobals;
138+
139+
#[php_function]
140+
pub fn get_all_cookies() -> ZBox<ZendHashTable> {
141+
ProcessGlobals::get().http_cookie_vars().to_owned()
142+
}
143+
144+
#[php_function]
145+
pub fn get_all_get_params() -> ZBox<ZendHashTable> {
146+
ProcessGlobals::get().http_get_vars().to_owned()
147+
}
148+
149+
#[php_function]
150+
pub fn get_server_vars() -> Option<ZBox<ZendHashTable>> {
151+
Some(ProcessGlobals::get().http_server_vars()?.to_owned())
152+
}
153+
# fn main() {}
154+
```
155+
156+
## SAPI Request Information
157+
158+
For lower-level request information, use `SapiGlobals`:
159+
160+
```rust,no_run
161+
# #![cfg_attr(windows, feature(abi_vectorcall))]
162+
# extern crate ext_php_rs;
163+
use ext_php_rs::prelude::*;
164+
use ext_php_rs::zend::SapiGlobals;
165+
166+
#[php_function]
167+
pub fn get_request_info() -> Vec<String> {
168+
let globals = SapiGlobals::get();
169+
let request_info = globals.request_info();
170+
171+
let mut info = Vec::new();
172+
173+
if let Some(method) = request_info.request_method() {
174+
info.push(format!("Method: {}", method));
175+
}
176+
if let Some(uri) = request_info.request_uri() {
177+
info.push(format!("URI: {}", uri));
178+
}
179+
if let Some(query) = request_info.query_string() {
180+
info.push(format!("Query: {}", query));
181+
}
182+
if let Some(content_type) = request_info.content_type() {
183+
info.push(format!("Content-Type: {}", content_type));
184+
}
185+
info.push(format!("Content-Length: {}", request_info.content_length()));
186+
187+
info
188+
}
189+
# fn main() {}
190+
```
191+
192+
### Available Request Info Methods
193+
194+
| Method | Description |
195+
|---------------------|-------------------------------|
196+
| `request_method()` | HTTP method (GET, POST, etc.) |
197+
| `request_uri()` | Request URI |
198+
| `query_string()` | Query string |
199+
| `cookie_data()` | Raw cookie data |
200+
| `content_type()` | Content-Type header |
201+
| `content_length()` | Content-Length value |
202+
| `path_translated()` | Translated filesystem path |
203+
| `auth_user()` | HTTP Basic auth username |
204+
| `auth_password()` | HTTP Basic auth password |
205+
206+
## Accessing Constants
207+
208+
Use `ExecutorGlobals` to access PHP constants:
209+
210+
```rust,no_run
211+
# #![cfg_attr(windows, feature(abi_vectorcall))]
212+
# extern crate ext_php_rs;
213+
use ext_php_rs::prelude::*;
214+
use ext_php_rs::zend::ExecutorGlobals;
215+
216+
#[php_function]
217+
pub fn get_php_version_constant() -> Option<String> {
218+
let globals = ExecutorGlobals::get();
219+
globals
220+
.constants()?
221+
.get("PHP_VERSION")
222+
.and_then(|zval| zval.string())
223+
}
224+
225+
#[php_function]
226+
pub fn constant_exists(name: String) -> bool {
227+
let globals = ExecutorGlobals::get();
228+
globals
229+
.constants()
230+
.is_some_and(|c| c.get(name.as_str()).is_some())
231+
}
232+
# fn main() {}
233+
```
234+
235+
## Accessing INI Values
236+
237+
```rust,no_run
238+
# #![cfg_attr(windows, feature(abi_vectorcall))]
239+
# extern crate ext_php_rs;
240+
use ext_php_rs::prelude::*;
241+
use ext_php_rs::zend::ExecutorGlobals;
242+
243+
#[php_function]
244+
pub fn get_memory_limit() -> Option<String> {
245+
ExecutorGlobals::get()
246+
.ini_values()
247+
.get("memory_limit")
248+
.cloned()
249+
.flatten()
250+
}
251+
252+
#[php_function]
253+
pub fn get_all_ini_values() -> Vec<(String, String)> {
254+
ExecutorGlobals::get()
255+
.ini_values()
256+
.iter()
257+
.filter_map(|(k, v)| {
258+
v.as_ref().map(|val| (k.clone(), val.clone()))
259+
})
260+
.collect()
261+
}
262+
# fn main() {}
263+
```
264+
265+
## Thread Safety
266+
267+
All global access methods use guard types that provide thread-safe access:
268+
269+
- `ProcessGlobals::get()` returns a `GlobalReadGuard<ProcessGlobals>`
270+
- `ExecutorGlobals::get()` returns a `GlobalReadGuard<ExecutorGlobals>`
271+
- `SapiGlobals::get()` returns a `GlobalReadGuard<SapiGlobals>`
272+
273+
The guard is automatically released when it goes out of scope. For mutable
274+
access (rarely needed), use `get_mut()`:
275+
276+
```rust,no_run
277+
# #![cfg_attr(windows, feature(abi_vectorcall))]
278+
# extern crate ext_php_rs;
279+
use ext_php_rs::zend::ExecutorGlobals;
280+
281+
fn example() {
282+
// Read-only access (most common)
283+
let globals = ExecutorGlobals::get();
284+
// ... use globals ...
285+
// Guard released when `globals` goes out of scope
286+
287+
// Mutable access (rarely needed)
288+
let mut globals = ExecutorGlobals::get_mut();
289+
// ... modify globals ...
290+
}
291+
# fn main() {}
292+
```
293+
294+
## PHP Example
295+
296+
```php
297+
<?php
298+
299+
// Assuming you've registered the functions above
300+
301+
// Access cookies
302+
$session_id = get_cookie('session_id');
303+
304+
// Access query parameters
305+
$page = get_query_param('page') ?? '1';
306+
307+
// Get request method
308+
$method = get_request_method(); // "GET", "POST", etc.
309+
310+
// Get all cookies as array
311+
$all_cookies = get_all_cookies();
312+
print_r($all_cookies);
313+
314+
// Get request info
315+
$info = get_request_info();
316+
print_r($info);
317+
318+
// Access constants
319+
$php_version = get_php_version_constant();
320+
echo "PHP Version: $php_version\n";
321+
322+
// Check if constant exists
323+
if (constant_exists('MY_CUSTOM_CONSTANT')) {
324+
echo "Constant exists!\n";
325+
}
326+
```
327+
328+
## Summary
329+
330+
| Type | Use Case |
331+
|-------------------|---------------------------------------------------------|
332+
| `ProcessGlobals` | HTTP superglobals (`$_GET`, `$_POST`, `$_COOKIE`, etc.) |
333+
| `SapiGlobals` | Low-level request info, headers |
334+
| `ExecutorGlobals` | Constants, INI values, function/class tables |
335+
336+
All types are accessed via `::get()` for read access or `::get_mut()` for write
337+
access, and provide thread-safe access through guard types.

0 commit comments

Comments
 (0)