Persistent, hardened PHP 8.4 runtime β RoadRunner + typed std library. Zero silent failures.
2.2K
A production-grade, persistent PHP 8.4 runtime that brings JVM-like stability to PHP.
PHP traditionally re-initializes on every request. CorePHP eliminates this by running PHP inside RoadRunner as a long-lived process β just like the JVM. It also replaces PHP's silent-failure standard library with one that throws typed exceptions on every error.
# Latest stable release
docker pull greicodex/corephp-vm:latest
# Specific version
docker pull greicodex/corephp-vm:1.0.0
# Latest development build (main branch)
docker pull greicodex/corephp-vm:edge
Use as your base image:
FROM greicodex/corephp-vm:latest
COPY . /app
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Docker Container β
β β
β RoadRunner (port 8080) β
β βββ worker.php (long-lived PHP process) β
β βββ bootstrap.php (auto_prepend_file) β
β βββ Error handler β ErrorExceptionβ
β βββ FunctionOverrider (runkit7) β
β βββ StrictObject β
β β
β php.ini hardening β
β βββ disable_functions (unserialize, exec...) β
β βββ allow_url_fopen = Off β
β βββ runkit.internal_override = 1 β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
| Layer | Mechanism | When |
|---|---|---|
| Static | PHPStan Level 9 + PHP-CS-Fixer | CI / pre-commit |
| Boot | runkit7 FunctionOverrider | Once at process startup |
| Runtime | bootstrap.php error handler | Every request |
FROM greicodex/corephp-vm:latest
WORKDIR /app
COPY . .
RUN composer install --no-dev --optimize-autoloader
CMD ["rr", "serve", "-c", "/app/.rr.yaml"]
services:
app:
image: greicodex/corephp-vm:latest
ports:
- "8080:8080"
volumes:
- .:/app
docker compose up -d
Your application is now running at http://localhost:8080.
std)All classes are under the core\ namespace and are automatically available via Composer autoload.
use core\Internal\Array\TypedCollection;
// Class type enforcement
$users = new TypedCollection(User::class);
$users->add(new User('Alice')); // OK
$users->add('not a user'); // throws InvalidArgumentException immediately
// Primitive type enforcement
$ids = new TypedCollection('int');
$ids->add(42); // OK
$ids->add('foo'); // throws InvalidArgumentException
// Iteration + filtering
foreach ($users as $user) {
echo $user->name . PHP_EOL;
}
$admins = $users->filter(fn(User $u) => $u->isAdmin());
use core\Net\Http\HttpClient;
use core\Net\Http\HttpException;
$client = new HttpClient(timeout: 10, strictStatus: true);
try {
$response = $client->get('https://api.example.com/users');
$users = $response->json(associative: true); // throws on non-JSON body
$status = $response->statusCode(); // 200
$type = $response->header('content-type'); // string or null
// POST with JSON body (array β auto-encoded)
$created = $client->post('https://api.example.com/users', ['name' => 'Alice']);
} catch (HttpException $e) {
// curl error, connection refused, timeout, or 4xx/5xx (in strictStatus mode)
}
s_*() Function ShimsBacked by azjezz/pslβ , these replace PHP's silent-failure built-ins. No use statement required β always available:
// JSON β throws on invalid input (never returns null/false)
$data = s_json('{"key":"value"}'); // array
$json = s_enc(['key' => 'value']); // string
$json = s_enc(['key' => 'value'], true); // pretty-printed
// Type coercion β throws CoercionException (not silent 0)
$id = s_int('42'); // 42
$id = s_int('hello'); // throws CoercionException
$n = s_float('3.14');
$str = s_str(42); // "42"
// File I/O β throws on error (never returns false)
$contents = s_file('/etc/hostname');
$bytes = s_write('/tmp/out.txt', 'hello');
$bytes = s_append('/tmp/out.txt', ' world');
// Regex β throws on bad pattern (never returns false)
s_match('/^\d+$/', '123'); // true / false
s_regex('/(\d+)-(\d+)/', '10-99'); // ['10', '99'] or null
// Environment β throws if missing (never returns empty string silently)
s_env('APP_KEY'); // string or throws
s_env_or('APP_ENV', 'production'); // string with fallback
// HTTP β throws HttpException on any failure
$r = s_get('https://api.example.com/users');
$r = s_post('https://api.example.com', ['name' => 'Alice']);
php.ini)The following functions are permanently disabled at the PHP engine level:
unserialize, serialize, exec, shell_exec, system, passthru,
proc_open, popen, pcntl_exec, pcntl_fork, pcntl_signal,
posix_kill, posix_setuid, posix_setgid, dl, phpinfo,
symlink, link, putenv, ini_set, ini_restore, show_source, highlight_file
| Function | Old Failure | New Behaviour |
|---|---|---|
json_decode() | returns null | throws JsonException |
json_encode() | returns false | throws JsonException |
file_get_contents() | returns false | throws FileReadException |
file_put_contents() | returns false | throws FileWriteException |
intval() | returns 0 silently | throws TypeCoercionException |
floatval() | returns 0.0 silently | throws TypeCoercionException |
preg_match() | returns false | throws RegexException |
preg_replace() | returns null | throws RegexException |
curl_exec() | returns false | throws HttpException |
base64_decode() | returns false | throws EncodingException |
If you cannot use Docker (cPanel, Plesk), a subset of features is available via .user.ini:
| Feature | Docker + RoadRunner | Shared Hosting |
|---|---|---|
| Persistent process | β | β (restarts per request) |
| runkit7 overrides | β | β |
| bootstrap.php sandbox | β | β |
| StrictObject | β | β |
Global s_*() shims | β | β |
| Error β Exception | β | β |
GPL-3.0 β see LICENSEβ
Content type
Image
Digest
sha256:5ac10a7f7β¦
Size
67.6 MB
Last updated
2 months ago
docker pull greicodex/corephp-vm