Skip to content

Commit 946110b

Browse files
committed
update
1 parent cadffe8 commit 946110b

File tree

6 files changed

+737
-1
lines changed

6 files changed

+737
-1
lines changed

03-docs.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ And there is more information available about specific topics:
2020
* [Cache](/docs/cache)
2121
* [Session](/docs/session)
2222
* [Authentication](/docs/authentication)
23+
24+
Advanced topics:
25+
26+
* [Webservers](/docs/webservers)
2327
* [Totp](/docs/totp)
2428
* [Firewall](/docs/firewall)
25-
* [Webservers](/docs/webservers)
29+
* [Analyzer](/docs/analyzer)
30+
* [Template](/docs/template)

04-api.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,15 @@ This is a reference of all global variables and functions.
140140
| Function | Location | Purpose |
141141
| ------------------------------------------- | ------------- | -------------------- |
142142
| `Firewall::start():void ` | *.php | Start rate limiting |
143+
144+
## Analyzer
145+
146+
| Function | Location | Purpose |
147+
| ------------------------------------------- | ------------- | -------------------- |
148+
| `Analyzer::execute():void ` | *.php | Check code quality |
149+
150+
## Template
151+
152+
| Function | Location | Purpose |
153+
| ---------------------------------------------- | ------------- | -------------------- |
154+
| `Template::render($tpl,$data,$fns=[]):string` | *.php | Render template |

docs/analyzer.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
layout: page
3+
title: Analyzer
4+
permalink: /docs/analyzer/
5+
---
6+
7+
The "Analyzer" class checks PHP files for disallowed output functions to ensure proper separation between logic (actions) and presentation (views), maintaining clean MVC architecture.
8+
9+
## Execute
10+
11+
```
12+
Analyzer::execute(): void
13+
```
14+
15+
Execute the analyzer to check all action and view files in the current request. This is automatically called by the framework when debug mode is enabled.
16+
17+
The analyzer checks:
18+
- Template actions
19+
- Page actions
20+
- Views
21+
- Template views
22+
23+
For disallowed functions that could break the MVC pattern.
24+
25+
Example:
26+
27+
```
28+
if (Debugger::$enabled) {
29+
Analyzer::execute();
30+
}
31+
```
32+
33+
## What It Checks
34+
35+
The Analyzer looks for these disallowed functions in your code:
36+
37+
### In Actions (*.php files)
38+
39+
Actions should not directly output content. These functions are not allowed:
40+
- `echo` - Use variables instead
41+
- `print` - Use variables instead
42+
- `exit` - Use `Router::redirect()` instead
43+
- `die` - Use `Router::redirect()` instead
44+
- `var_dump` - Use `d()` function instead
45+
- `eval` - Security risk, avoid entirely
46+
47+
### In Views (*.phtml files)
48+
49+
Views should use the `e()` function for safe output. These are not allowed:
50+
- `echo` - Use `e()` function instead
51+
- `print` - Use `e()` function instead
52+
- `<?= ?>` short tags - Use `<?php e($var); ?>` instead
53+
- `exit`, `die` - Should not be in views
54+
- `var_dump` - Use `d()` function instead
55+
- `eval` - Security risk, avoid entirely
56+
57+
## Why This Matters
58+
59+
The analyzer enforces MintyPHP's clean separation of concerns:
60+
61+
**Actions (*.php)** handle logic:
62+
```php
63+
<?php
64+
// Good: Store data in variables
65+
$users = DB::select('SELECT * FROM users');
66+
$total = count($users);
67+
68+
// Bad: Direct output in action
69+
echo "Total users: " . $total; // Will trigger warning
70+
```
71+
72+
**Views (*.phtml)** handle presentation:
73+
```php
74+
<?php
75+
// Good: Use e() function for safe output
76+
<h1>Users</h1>
77+
<p>Total: <?php e($total); ?></p>
78+
79+
// Bad: Use of echo
80+
<p>Total: <?php echo $total; ?></p> // Will trigger warning
81+
```
82+
83+
## Example Warnings
84+
85+
When the analyzer detects violations, it triggers warnings like:
86+
87+
```
88+
Warning: MintyPHP action "pages/users/list().php" should not use "echo". Error raised in...
89+
```
90+
91+
```
92+
Warning: MintyPHP view "pages/users/list(default).phtml" should not use "echo". Error raised in...
93+
```
94+
95+
## Best Practices
96+
97+
### In Actions
98+
99+
**Good:**
100+
```php
101+
<?php
102+
use MintyPHP\DB;
103+
use MintyPHP\Router;
104+
105+
// Fetch data
106+
$users = DB::select('SELECT * FROM users');
107+
108+
// Process data
109+
$activeUsers = array_filter($users, fn($u) => $u['active']);
110+
111+
// Handle redirects properly
112+
if (empty($activeUsers)) {
113+
Router::redirect('error/not_found');
114+
}
115+
```
116+
117+
**Bad:**
118+
```php
119+
<?php
120+
// Don't output directly
121+
echo "<h1>Users</h1>";
122+
print_r($users);
123+
124+
// Don't use exit/die
125+
if (empty($users)) {
126+
die('No users found');
127+
}
128+
129+
// Don't use var_dump
130+
var_dump($users);
131+
```
132+
133+
### In Views
134+
135+
**Good:**
136+
```php
137+
<?php
138+
use MintyPHP\Session;
139+
140+
<form method="post">
141+
<input name="username" />
142+
<button type="submit">Login</button>
143+
<?php Session::getCsrfInput(); ?>
144+
</form>
145+
146+
<?php foreach ($users as $user): ?>
147+
<p><?php e($user['name']); ?></p>
148+
<?php endforeach; ?>
149+
```
150+
151+
**Bad:**
152+
```php
153+
<!-- Don't use short echo tags -->
154+
<p><?= $user['name'] ?></p>
155+
156+
<!-- Don't use echo directly -->
157+
<p><?php echo $user['name']; ?></p>
158+
159+
<!-- Don't use print -->
160+
<?php print $message; ?>
161+
```
162+
163+
## Debugging Output
164+
165+
Instead of `var_dump()` or `print_r()`, use the `d()` function which integrates with the debugger:
166+
167+
```php
168+
<?php
169+
// In actions
170+
$user = DB::selectOne('SELECT * FROM users WHERE id = ?', $userId);
171+
d($user); // Outputs to debugger panel, not page
172+
173+
// Multiple values
174+
d($user, $permissions, $settings);
175+
```
176+
177+
The `d()` function:
178+
- Only works when debugger is enabled
179+
- Logs to the "Logging" panel in the debugger
180+
- Includes file and line number information
181+
- Limits output to prevent memory issues
182+
183+
## Configuration
184+
185+
The Analyzer runs automatically when the debugger is enabled. Enable it in `config/config.php`:
186+
187+
```php
188+
use MintyPHP\Debugger;
189+
190+
Debugger::$enabled = true; // Analyzer runs automatically
191+
```
192+
193+
## When It Runs
194+
195+
The Analyzer is executed automatically:
196+
1. After routing is complete
197+
2. Before actions and views are loaded
198+
3. Only when `Debugger::$enabled` is true
199+
200+
This means violations are caught during development but don't affect production performance.
201+

docs/firewall.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
layout: page
3+
title: Firewall
4+
permalink: /docs/firewall/
5+
---
6+
7+
The "Firewall" class provides rate limiting and request concurrency control to protect your application from abuse by limiting the number of concurrent requests from the same IP address.
8+
9+
## Start
10+
11+
```
12+
Firewall::start(): void
13+
```
14+
15+
Start the firewall to protect against concurrent request floods. This uses a spin-lock mechanism with Memcached to ensure requests wait rather than fail immediately.
16+
17+
The firewall counts concurrent requests per IP address and enforces a configurable limit. When the limit is reached, additional requests are delayed using a spin-lock.
18+
19+
Example:
20+
21+
```
22+
Firewall::start();
23+
// Application continues only after acquiring a slot
24+
```
25+
26+
This is typically called at the beginning of your application, right before starting the session:
27+
28+
```
29+
// Start the firewall
30+
Firewall::start();
31+
32+
// Start the session
33+
Session::start();
34+
```
35+
36+
## Configuration
37+
38+
The Firewall can be configured by setting static properties in `config/config.php`:
39+
40+
```
41+
Firewall::$concurrency = 10; // Max concurrent requests per IP
42+
Firewall::$spinLockSeconds = 0.15; // Time to wait between retry attempts
43+
Firewall::$intervalSeconds = 300; // Time window for rate limiting
44+
Firewall::$cachePrefix = 'fw_concurrency_'; // Cache key prefix
45+
Firewall::$reverseProxy = false; // Set true if behind reverse proxy
46+
```
47+
48+
### Concurrency
49+
50+
The maximum number of concurrent requests allowed from a single IP address. Default is 10.
51+
52+
```
53+
Firewall::$concurrency = 5; // Only allow 5 concurrent requests
54+
```
55+
56+
### Spin Lock Seconds
57+
58+
The time in seconds to wait between retry attempts when the concurrency limit is reached. Default is 0.15 seconds (150ms).
59+
60+
```
61+
Firewall::$spinLockSeconds = 0.2; // Wait 200ms between retries
62+
```
63+
64+
### Interval Seconds
65+
66+
The time window in seconds for tracking concurrent requests. Default is 300 seconds (5 minutes).
67+
68+
```
69+
Firewall::$intervalSeconds = 600; // Track over 10 minute window
70+
```
71+
72+
### Cache Prefix
73+
74+
The prefix used for cache keys to avoid collisions. Default is 'fw_concurrency_'.
75+
76+
```
77+
Firewall::$cachePrefix = 'my_firewall_';
78+
```
79+
80+
### Reverse Proxy
81+
82+
Set to true if your application is behind a reverse proxy (like nginx or Apache) to correctly identify client IP addresses. Default is false.
83+
84+
```
85+
Firewall::$reverseProxy = true; // Trust X-Forwarded-For header
86+
```
87+
88+
## How It Works
89+
90+
1. When a request arrives, the firewall checks how many concurrent requests are currently being processed from that IP
91+
2. If below the limit, the request proceeds and a counter is incremented
92+
3. If at the limit, the firewall enters a spin-lock, waiting briefly and checking again
93+
4. Once the request completes, the counter is decremented
94+
5. IP addresses are identified using `REMOTE_ADDR` or `HTTP_X_FORWARDED_FOR` (if `$reverseProxy` is enabled)
95+
96+
This prevents denial-of-service attacks where many requests flood the server simultaneously, while still allowing legitimate concurrent requests within reasonable limits.

0 commit comments

Comments
 (0)