ffi/env
Small PHP utility for detecting the FFI runtime environment. Get FFI status (enabled/disabled/CLI-only/not available), check availability, or assert FFI is usable with clear exceptions/messages. Useful for guarding FFI-dependent code paths.
Installation:
composer require ffi/env
Ensure your project meets the PHP ≥ 7.4 requirement.
First Check:
use FFI\Env\Runtime;
$status = Runtime::getStatus();
Verify FFI availability in your environment (CLI, web, or embedded).
Basic Assertion:
Runtime::assertAvailable(); // Throws if unavailable
Use this early in your application lifecycle (e.g., in a service provider or bootstrap file).
Dynamic FFI Feature Toggle:
// In a service provider or config loader
if (Runtime::isAvailable()) {
$this->app->singleton(FFIService::class, fn() => new FFIService());
} else {
$this->app->singleton(FFIService::class, fn() => new FallbackService());
}
Leverage the package to conditionally enable FFI-dependent features while gracefully falling back.
Bootstrap Validation:
// In `bootstrap/app.php` or a service provider
Runtime::assertAvailable();
// Proceed with FFI-heavy logic
Environment-Specific Logic:
if (Runtime::isCliEnabled()) {
// CLI-only FFI optimizations
} elseif (Runtime::isWebEnabled()) {
// Web-safe FFI usage
}
Dependency Injection:
// In Laravel's `AppServiceProvider`
public function register()
{
$this->app->when(FFIService::class)
->needs('$ffiAvailable')
->give(fn() => Runtime::isAvailable());
}
Runtime::assertAvailable() in boot() to fail fast if FFI is unavailable.public function handle($request, Closure $next)
{
if (!Runtime::isAvailable()) {
abort(503, 'FFI unavailable');
}
return $next($request);
}
Runtime::isAvailable() in tests to simulate FFI-unavailable environments:
$this->partialMock(Runtime::class, ['isAvailable'])
->method('isAvailable')
->willReturn(false);
False Positives in Web Contexts:
Runtime::isAvailable() may return true in web requests even if FFI is disabled in php.ini.Runtime::getStatus() === Status::ENABLED for strict checks.Embedded SAPI Misclassification:
embed/micro/phpdbg as non-CLI.if (in_array(PHP_SAPI, ['embed', 'micro', 'phpdbg'])) {
// Handle embedded SAPI
}
PHP 8.4+ Deprecations:
extension_loaded() may trigger deprecation warnings.Runtime::isAvailable() instead of direct FFI checks.Status Ambiguity: Log the full status for clarity:
dump([
'status' => Runtime::getStatus(),
'sapi' => PHP_SAPI,
'ffi_loaded' => extension_loaded('ffi'),
]);
Preload Issues: If using FFI preloads, verify:
if (Runtime::isCliEnabled() && !extension_loaded('ffi')) {
// Check preload configuration
}
Custom Status Handling:
Extend the Status enum for project-specific states:
namespace App\FFI;
use FFI\Env\Status;
final class CustomStatus extends Status {
public const PARTIALLY_AVAILABLE = 'partially_available';
}
Environment-Specific Factories:
// app/Providers/FFIServiceProvider.php
public function register()
{
$this->app->bind(
FFIInterface::class,
fn() => Runtime::isCliEnabled()
? new CLIFFIService()
: new WebFFIService()
);
}
Event Listeners: Trigger events when FFI status changes (e.g., in a custom event dispatcher):
event(new FFIStatusChanged(Runtime::getStatus()));
How can I help you explore Laravel packages today?