php-networking
1
总安装量
1
周安装量
#52940
全站排名
安装命令
npx skills add https://github.com/peixotorms/odinlayer-skills --skill php-networking
Agent 安装分布
amp
1
opencode
1
kimi-cli
1
codex
1
github-copilot
1
claude-code
1
Skill 文档
PHP Networking, Regex & Parallel Execution
cURL & HTTP Requests
Basic Request
$ch = curl_init('https://api.example.com/data');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Accept: application/json', 'Authorization: Bearer ' . $token],
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true, // NEVER disable in production
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException(curl_error($ch), curl_errno($ch));
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// curl_close() optional in PHP 8+ (garbage collected)
POST / PUT / JSON
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
]);
// Custom method (PUT, PATCH, DELETE)
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
Multi-cURL (Parallel Requests)
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $key => $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
curl_multi_add_handle($mh, $ch);
$handles[$key] = $ch;
}
// Run all in parallel
do {
$status = curl_multi_exec($mh, $running);
if ($running) { curl_multi_select($mh); } // block until I/O ready
} while ($running > 0);
// Collect results
$results = [];
foreach ($handles as $key => $ch) {
$results[$key] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
cURL Reference
| Option | Purpose |
|---|---|
CURLOPT_RETURNTRANSFER |
Return body as string (not print) |
CURLOPT_TIMEOUT |
Total operation timeout (seconds) |
CURLOPT_CONNECTTIMEOUT |
Connection phase timeout |
CURLOPT_FOLLOWLOCATION |
Auto-follow redirects |
CURLOPT_MAXREDIRS |
Max redirects to follow |
CURLOPT_USERPWD |
Basic auth "user:pass" |
CURLOPT_ACCEPT_ENCODING |
Enable gzip/deflate (auto-decompressed) |
CURLOPT_SSL_VERIFYPEER |
Verify server certificate (default true) |
CURLOPT_SSL_VERIFYHOST |
Verify hostname in cert (use 2) |
CURLOPT_HTTPHEADER |
Custom request headers array |
CURLOPT_POSTFIELDS |
POST data (string or array) |
CurlHandle (PHP 8.0+) |
Opaque final class, replaces resource type |
| Rule | Detail |
|---|---|
| Always set timeouts | Prevent hanging on slow servers |
| Never disable SSL verification | Except in dev/test |
Use === for curl_exec() check |
Returns false on failure, not falsy |
| HTTP 4xx/5xx is not curl failure | Check CURLINFO_HTTP_CODE separately |
| Multi-curl for parallel | Much faster than sequential for multiple URLs |
Regular Expressions (PCRE)
Key Functions
// Match â returns 1 (match), 0 (no match), false (error)
preg_match('/^[a-z]+$/i', $input, $matches);
// Match all â returns count of matches
preg_match_all('/\d+/', $text, $matches);
// Replace â string or callback
$clean = preg_replace('/\s+/', ' ', $text);
$result = preg_replace_callback('/\{(\w+)\}/', fn($m) => $vars[$m[1]] ?? '', $template);
// Split
$parts = preg_split('/[\s,]+/', $csv);
// Always check for errors
if (preg_last_error() !== PREG_NO_ERROR) {
throw new RuntimeException(preg_last_error_msg());
}
Modifiers
| Modifier | Effect |
|---|---|
i |
Case-insensitive |
m |
^/$ match line boundaries (not just string start/end) |
s |
. matches newlines |
x |
Ignore whitespace + # comments in pattern |
u |
UTF-8 mode â required for multibyte strings |
U |
Invert greediness (all quantifiers ungreedy by default) |
n |
Only named groups (?<name>) capture (PHP 8.2+) |
D |
$ matches only absolute end, not before final \n |
A |
Anchor to string start |
Named Captures & Assertions
// Named captures â cleaner than $matches[1]
preg_match('/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/', $date, $m);
echo $m['year']; // "2024"
// Lookahead/lookbehind (zero-width assertions)
'/(?<=\$)\d+/' // Positive lookbehind: digits after $
'/\d+(?= USD)/' // Positive lookahead: digits before " USD"
'/foo(?!bar)/' // Negative lookahead: "foo" not followed by "bar"
ReDoS Prevention & Performance
| Rule | Detail |
|---|---|
| Avoid nested quantifiers | (a+)*, (a*)+ cause exponential backtracking |
Use atomic groups (?>...) |
Prevent backtracking into group |
| Character classes over alternation | [aeiou] faster than (a|e|i|o|u) |
| Anchor patterns | ^pattern / \Apattern fastest |
Check preg_last_error() |
Detect PREG_BACKTRACK_LIMIT_ERROR |
pcre.backtrack_limit |
Default 1M â may hit on large subjects |
| Lookbehind must be fixed-length | Variable-length lookbehind not supported |
Parallel & Async Patterns
Process Control (pcntl)
$pid = pcntl_fork();
if ($pid === -1) {
throw new RuntimeException('Fork failed');
} elseif ($pid > 0) {
// Parent â wait for child to prevent zombies
pcntl_wait($status);
} else {
// Child (pid === 0)
doWork();
exit(0);
}
Non-Blocking I/O with stream_select
stream_set_blocking($stream, false);
$read = [$stream1, $stream2, $stream3];
$write = $except = [];
// Block up to 200ms waiting for any stream to be ready
if (stream_select($read, $write, $except, 0, 200000) > 0) {
foreach ($read as $ready) {
$data = fread($ready, 8192);
}
}
parallel Extension (Modern Async)
$runtime = new parallel\Runtime();
$futures = [];
foreach ($tasks as $i => $task) {
$futures[$i] = $runtime->run(fn() => processTask($task), [$task]);
}
// Collect results (blocks if not ready)
foreach ($futures as $i => $future) {
$results[$i] = $future->value();
}
$runtime->close();
Comparison
| Approach | Best for | Notes |
|---|---|---|
curl_multi_* |
Parallel HTTP requests | Built-in, no extensions needed |
pcntl_fork() |
CPU-bound parallel work | Unix only, not thread-safe |
stream_select() |
High-concurrency I/O | Event loop pattern, thousands of connections |
parallel extension |
General async tasks | Requires ZTS PHP, message-passing model |
| Fibers (8.1+) | Cooperative concurrency | Single-thread, no true parallelism |
| Rule | Detail |
|---|---|
pcntl_fork() workers |
Match CPU count (2-4) |
stream_select() timeout |
Min 200ms to avoid CPU spin |