Skip to content

Instantly share code, notes, and snippets.

@ahsankhatri
Created September 11, 2025 14:52
Show Gist options
  • Save ahsankhatri/4e13ec392c9b978283acbe9c3e933ec9 to your computer and use it in GitHub Desktop.
Save ahsankhatri/4e13ec392c9b978283acbe9c3e933ec9 to your computer and use it in GitHub Desktop.
A utility to check server requirements for Laravel framework versions 10-12 (can be added). Supports both CLI and Web interfaces
<?php
/**
* Laravel Requirements Checker
*
* A utility to check server requirements for Laravel framework versions 10-12
* Supports both CLI and Web interfaces
*
* Usage (CLI): php laravel-requirements-checker.php [--version=10|11|12] [--format=text|json]
* Usage (Web): Access via browser
*/
class LaravelRequirementsChecker
{
public const DEFAULT_VERSION = 12;
private array $requirements = [
'10' => [
'name' => 'Laravel 10.x',
'php_version' => '8.1.0',
'required_extensions' => [
'ctype', 'curl', 'dom', 'fileinfo', 'filter', 'hash', 'json',
'mbstring', 'openssl', 'pcre', 'pdo', 'session', 'tokenizer', 'xml'
],
'recommended_extensions' => [
'bcmath', 'gd', 'imagick', 'intl', 'zip', 'redis', 'memcached',
'pcntl', 'pdo_mysql', 'xmlwriter',
]
],
'11' => [
'name' => 'Laravel 11.x',
'php_version' => '8.2.0',
'required_extensions' => [
'ctype', 'curl', 'dom', 'fileinfo', 'filter', 'hash', 'json',
'mbstring', 'openssl', 'pcre', 'pdo', 'session', 'tokenizer', 'xml'
],
'recommended_extensions' => [
'bcmath', 'gd', 'imagick', 'intl', 'zip', 'redis', 'memcached',
'pcntl', 'pdo_mysql', 'xmlwriter',
]
],
'12' => [
'name' => 'Laravel 12.x',
'php_version' => '8.2.0',
'required_extensions' => [
'ctype', 'curl', 'dom', 'fileinfo', 'filter', 'hash', 'json',
'mbstring', 'openssl', 'pcre', 'pdo', 'session', 'tokenizer', 'xml'
],
'recommended_extensions' => [
'bcmath', 'gd', 'imagick', 'intl', 'zip', 'redis', 'memcached',
'pcntl', 'pdo_mysql', 'xmlwriter',
]
]
];
private string $laravelVersion;
private string $outputFormat;
private bool $isCliMode;
public function __construct()
{
$this->isCliMode = php_sapi_name() === 'cli';
$this->laravelVersion = $this->getRequestedVersion();
$this->outputFormat = $this->getOutputFormat();
}
private function getRequestedVersion(): string
{
if ($this->isCliMode) {
$options = getopt('', ['version::', 'format::']);
return $options['version'] ?? self::DEFAULT_VERSION;
} else {
return $_GET['version'] ?? self::DEFAULT_VERSION;
}
}
private function getOutputFormat(): string
{
if ($this->isCliMode) {
$options = getopt('', ['version::', 'format::']);
return $options['format'] ?? 'text';
} else {
return $_GET['format'] ?? 'html';
}
}
public function run(): void
{
if (!isset($this->requirements[$this->laravelVersion])) {
$this->displayError("Unsupported Laravel version: {$this->laravelVersion}. Supported versions: " . implode(', ', array_keys($this->requirements)));
return;
}
$results = $this->checkRequirements();
switch ($this->outputFormat) {
case 'json':
$this->displayJsonOutput($results);
break;
case 'html':
$this->displayHtmlOutput($results);
break;
default:
$this->displayTextOutput($results);
}
}
private function checkRequirements(): array
{
$requirements = $this->requirements[$this->laravelVersion];
$results = [
'laravel_version' => $requirements['name'],
'server_info' => $this->getServerInfo(),
'php_check' => $this->checkPhpVersion($requirements['php_version']),
'required_extensions' => $this->checkExtensions($requirements['required_extensions'], true),
'recommended_extensions' => $this->checkExtensions($requirements['recommended_extensions'], false),
'additional_checks' => $this->performAdditionalChecks(),
'overall_status' => 'passed'
];
// Determine overall status
if (!$results['php_check']['passed']) {
$results['overall_status'] = 'failed';
} else {
foreach ($results['required_extensions'] as $ext) {
if (!$ext['installed']) {
$results['overall_status'] = 'failed';
break;
}
}
}
return $results;
}
private function getServerInfo(): array
{
return [
'php_version' => PHP_VERSION,
'php_sapi' => php_sapi_name(),
'os' => php_uname('s') . ' ' . php_uname('r'),
'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'CLI',
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
'post_max_size' => ini_get('post_max_size')
];
}
private function checkPhpVersion(string $requiredVersion): array
{
$currentVersion = PHP_VERSION;
$passed = version_compare($currentVersion, $requiredVersion, '>=');
return [
'required' => $requiredVersion,
'current' => $currentVersion,
'passed' => $passed,
'message' => $passed ? 'PHP version requirement met' : "PHP {$requiredVersion} or higher required, found {$currentVersion}"
];
}
private function checkExtensions(array $extensions, bool $required): array
{
$results = [];
foreach ($extensions as $extension) {
$installed = extension_loaded($extension);
$version = $installed ? phpversion($extension) : null;
$results[] = [
'name' => $extension,
'installed' => $installed,
'version' => $version ?: 'N/A',
'required' => $required,
'status' => $installed ? 'OK' : ($required ? 'MISSING' : 'RECOMMENDED')
];
}
return $results;
}
private function performAdditionalChecks(): array
{
$checks = [];
// Composer check
$composerPath = $this->findComposer();
$checks['composer'] = [
'name' => 'Composer',
'status' => $composerPath ? 'OK' : 'NOT FOUND',
'path' => $composerPath,
'version' => $composerPath ? $this->getComposerVersion($composerPath) : null
];
// Node.js check
$nodePath = $this->findExecutable('node');
$checks['nodejs'] = [
'name' => 'Node.js',
'status' => $nodePath ? 'OK' : 'NOT FOUND',
'path' => $nodePath,
'version' => $nodePath ? $this->getNodeVersion() : null
];
// NPM check
$npmPath = $this->findExecutable('npm');
$checks['npm'] = [
'name' => 'NPM',
'status' => $npmPath ? 'OK' : 'NOT FOUND',
'path' => $npmPath,
'version' => $npmPath ? $this->getNpmVersion() : null
];
// Directory permissions check (if in web context and Laravel directories exist)
if (!$this->isCliMode) {
$checks['permissions'] = $this->checkDirectoryPermissions();
}
return $checks;
}
private function findComposer(): ?string
{
$paths = ['composer', 'composer.phar', './composer.phar'];
foreach ($paths as $path) {
if ($this->commandExists($path)) {
return $path;
}
}
return null;
}
private function findExecutable(string $executable): ?string
{
if ($this->commandExists($executable)) {
return $executable;
}
return null;
}
private function commandExists(string $command): bool
{
$whereIsCommand = (PHP_OS == 'WINNT') ? 'where' : 'which';
$process = proc_open(
"$whereIsCommand $command",
[
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w']
],
$pipes,
null,
null,
['suppress_errors' => true]
);
if (is_resource($process)) {
$result = stream_get_contents($pipes[1]);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
return $return_value === 0 && !empty(trim($result));
}
return false;
}
private function getComposerVersion(?string $composerPath): ?string
{
if (!$composerPath) return null;
$output = shell_exec("$composerPath --version 2>/dev/null");
if (preg_match('/Composer version ([^\s]+)/', $output, $matches)) {
return $matches[1];
}
return 'Unknown';
}
private function getNodeVersion(): ?string
{
$output = shell_exec('node --version 2>/dev/null');
return $output ? trim($output) : null;
}
private function getNpmVersion(): ?string
{
$output = shell_exec('npm --version 2>/dev/null');
return $output ? trim($output) : null;
}
private function checkDirectoryPermissions(): array
{
$directories = ['storage', 'bootstrap/cache'];
$results = [];
foreach ($directories as $dir) {
if (is_dir($dir)) {
$writable = is_writable($dir);
$results[$dir] = [
'path' => $dir,
'exists' => true,
'writable' => $writable,
'permissions' => substr(sprintf('%o', fileperms($dir)), -4),
'status' => $writable ? 'OK' : 'NOT WRITABLE'
];
} else {
$results[$dir] = [
'path' => $dir,
'exists' => false,
'writable' => false,
'permissions' => 'N/A',
'status' => 'NOT FOUND'
];
}
}
return $results;
}
private function displayError(string $message): void
{
if ($this->isCliMode) {
echo "Error: $message\n";
} else {
echo "<div style='color: red; padding: 20px; border: 1px solid red; margin: 20px;'>Error: $message</div>";
}
}
private function displayJsonOutput(array $results): void
{
if (!$this->isCliMode) {
header('Content-Type: application/json');
}
echo json_encode($results, JSON_PRETTY_PRINT);
}
private function displayTextOutput(array $results): void
{
$output = [];
$output[] = str_repeat('=', 60);
$output[] = "LARAVEL REQUIREMENTS CHECK - {$results['laravel_version']}";
$output[] = str_repeat('=', 60);
// Server Info
$output[] = "\nπŸ“‹ SERVER INFORMATION:";
$output[] = str_repeat('-', 30);
$output[] = "PHP Version: {$results['server_info']['php_version']}";
$output[] = "PHP SAPI: {$results['server_info']['php_sapi']}";
$output[] = "Operating System: {$results['server_info']['os']}";
$output[] = "Memory Limit: {$results['server_info']['memory_limit']}";
// PHP Version Check
$output[] = "\n🐘 PHP VERSION CHECK:";
$output[] = str_repeat('-', 30);
$status = $results['php_check']['passed'] ? 'βœ… PASS' : '❌ FAIL';
$output[] = "{$status} - {$results['php_check']['message']}";
// Required Extensions
$output[] = "\nπŸ”§ REQUIRED EXTENSIONS:";
$output[] = str_repeat('-', 30);
foreach ($results['required_extensions'] as $ext) {
$status = $ext['installed'] ? 'βœ…' : '❌';
$version = $ext['version'] !== 'N/A' ? " (v{$ext['version']})" : '';
$output[] = "{$status} {$ext['name']}{$version} - {$ext['status']}";
}
// Recommended Extensions
$output[] = "\nπŸ’‘ RECOMMENDED EXTENSIONS:";
$output[] = str_repeat('-', 30);
foreach ($results['recommended_extensions'] as $ext) {
$status = $ext['installed'] ? 'βœ…' : '⚠️';
$version = $ext['version'] !== 'N/A' ? " (v{$ext['version']})" : '';
$output[] = "{$status} {$ext['name']}{$version} - {$ext['status']}";
}
// Additional Checks
$output[] = "\nπŸ› οΈ ADDITIONAL TOOLS:";
$output[] = str_repeat('-', 30);
foreach ($results['additional_checks'] as $key => $check) {
if ($key === 'permissions') continue; // Skip permissions in CLI
$status = $check['status'] === 'OK' ? 'βœ…' : '⚠️';
$version = $check['version'] ? " (v{$check['version']})" : '';
$output[] = "{$status} {$check['name']}{$version} - {$check['status']}";
}
// Overall Status
$output[] = "\n" . str_repeat('=', 60);
$overallStatus = $results['overall_status'] === 'passed' ? 'βœ… SYSTEM READY' : '❌ SYSTEM NOT READY';
$output[] = "OVERALL STATUS: {$overallStatus}";
$output[] = str_repeat('=', 60);
echo implode("\n", $output) . "\n";
}
private function displayHtmlOutput(array $results): void
{
if (!headers_sent()) {
header('Content-Type: text/html; charset=UTF-8');
}
$overallClass = $results['overall_status'] === 'passed' ? 'success' : 'danger';
$overallText = $results['overall_status'] === 'passed' ? 'SYSTEM READY FOR LARAVEL' : 'SYSTEM NOT READY';
$availableVersions = implode('', array_map(function ($x, $i) {
return sprintf('<a href="?version=%d" class="btn">%s</a>', $i, $x['name']);
}, $this->requirements, array_keys($this->requirements)));
echo <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Laravel Requirements Checker</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f8f9fa; padding: 20px; }
.container { max-width: 1200px; margin: 0 auto; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 10px; margin-bottom: 30px; text-align: center; }
.version-selector { background: white; padding: 20px; border-radius: 10px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.card { background: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.card h3 { margin-bottom: 15px; color: #333; border-bottom: 2px solid #eee; padding-bottom: 10px; }
.status-success { color: #28a745; font-weight: bold; }
.status-danger { color: #dc3545; font-weight: bold; }
.status-warning { color: #ffc107; font-weight: bold; }
.overall-status { padding: 20px; border-radius: 10px; text-align: center; font-size: 1.5em; font-weight: bold; margin-bottom: 30px; }
.overall-status.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.overall-status.danger { background: #f8d7da; color: #721c24; border: 1px solid #f1b0b7; }
.info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 10px; }
.info-item { padding: 10px; background: #f8f9fa; border-radius: 5px; }
.extension-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 10px; }
.extension-item { padding: 10px; border-radius: 5px; border-left: 4px solid #eee; background: #f8f9fa; }
.extension-item.ok { border-left-color: #28a745; }
.extension-item.missing { border-left-color: #dc3545; }
.extension-item.recommended { border-left-color: #ffc107; }
.btn { display: inline-block; padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; margin: 5px; }
.btn:hover { background: #0056b3; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>πŸš€ Laravel Requirements Checker</h1>
<p>Checking requirements for {$results['laravel_version']}</p>
</div>
<div class="version-selector">
<h3>Select Laravel Version:</h3>
{$availableVersions}
<a href="?format=json&version={$this->laravelVersion}" class="btn">JSON Output</a>
</div>
<div class="overall-status {$overallClass}">
{$overallText}
</div>
<div class="card">
<h3>πŸ“‹ Server Information</h3>
<div class="info-grid">
<div class="info-item"><strong>PHP Version:</strong> {$results['server_info']['php_version']}</div>
<div class="info-item"><strong>PHP SAPI:</strong> {$results['server_info']['php_sapi']}</div>
<div class="info-item"><strong>Operating System:</strong> {$results['server_info']['os']}</div>
<div class="info-item"><strong>Memory Limit:</strong> {$results['server_info']['memory_limit']}</div>
<div class="info-item"><strong>Max Execution Time:</strong> {$results['server_info']['max_execution_time']}s</div>
<div class="info-item"><strong>Upload Max Size:</strong> {$results['server_info']['upload_max_filesize']}</div>
</div>
</div>
<div class="card">
<h3>🐘 PHP Version Check</h3>
HTML;
$phpClass = $results['php_check']['passed'] ? 'ok' : 'missing';
$phpStatusClass = $results['php_check']['passed'] ? 'status-success' : 'status-danger';
$phpIcon = $results['php_check']['passed'] ? 'βœ… PASS' : '❌ FAIL';
echo <<<HTML
<div class="extension-item {$phpClass}">
<span class="{$phpStatusClass}">
{$phpIcon}
</span>
- {$results['php_check']['message']}
</div>
</div>
<div class="card">
<h3>πŸ”§ Required Extensions</h3>
<div class="extension-list">
HTML;
foreach ($results['required_extensions'] as $ext) {
$class = $ext['installed'] ? 'ok' : 'missing';
$statusClass = $ext['installed'] ? 'status-success' : 'status-danger';
$icon = $ext['installed'] ? 'βœ…' : '❌';
$version = $ext['version'] !== 'N/A' ? " (v{$ext['version']})" : '';
echo <<<HTML
<div class="extension-item {$class}">
<strong>{$ext['name']}</strong>{$version}<br>
<span class="{$statusClass}">{$icon} {$ext['status']}</span>
</div>
HTML;
}
echo <<<HTML
</div>
</div>
<div class="card">
<h3>πŸ’‘ Recommended Extensions</h3>
<div class="extension-list">
HTML;
foreach ($results['recommended_extensions'] as $ext) {
$class = $ext['installed'] ? 'ok' : 'recommended';
$statusClass = $ext['installed'] ? 'status-success' : 'status-warning';
$icon = $ext['installed'] ? 'βœ…' : '⚠️';
$version = $ext['version'] !== 'N/A' ? " (v{$ext['version']})" : '';
echo <<<HTML
<div class="extension-item {$class}">
<strong>{$ext['name']}</strong>{$version}<br>
<span class="{$statusClass}">{$icon} {$ext['status']}</span>
</div>
HTML;
}
echo <<<HTML
</div>
</div>
<div class="card">
<h3>πŸ› οΈ Additional Tools</h3>
<div class="extension-list">
HTML;
foreach ($results['additional_checks'] as $key => $check) {
if ($key === 'permissions') {
// Handle permissions separately
echo '<div class="card"><h3>πŸ“ Directory Permissions</h3><div class="extension-list">';
foreach ($check as $dir => $perm) {
$class = $perm['status'] === 'OK' ? 'ok' : 'missing';
$statusClass = $perm['status'] === 'OK' ? 'status-success' : 'status-danger';
$icon = $perm['status'] === 'OK' ? 'βœ…' : '❌';
$permissionLabel = $perm['exists'] ? " (Permissions: {$perm['permissions']})" : '';
echo <<<HTML
<div class="extension-item {$class}">
<strong>{$perm['path']}</strong><br>
<span class="{$statusClass}">{$icon} {$perm['status']}</span>
{$permissionLabel}
</div>
HTML;
}
echo '</div></div>';
continue;
}
$class = $check['status'] === 'OK' ? 'ok' : 'recommended';
$statusClass = $check['status'] === 'OK' ? 'status-success' : 'status-warning';
$icon = $check['status'] === 'OK' ? 'βœ…' : '⚠️';
$version = $check['version'] ? " (v{$check['version']})" : '';
echo <<<HTML
<div class="extension-item {$class}">
<strong>{$check['name']}</strong>{$version}<br>
<span class="{$statusClass}">{$icon} {$check['status']}</span>
</div>
HTML;
}
$timeGenerated = date('Y-m-d H:i:s');
echo <<<HTML
</div>
</div>
<div style="text-align: center; margin-top: 30px; padding: 20px; background: white; border-radius: 10px;">
<p>Generated on: {$timeGenerated}</p>
<p>Laravel Requirements Checker v1.0.0</p>
</div>
</div>
</body>
</html>
HTML;
}
}
// Main execution
try {
$checker = new LaravelRequirementsChecker();
$checker->run();
} catch (Exception $e) {
if (php_sapi_name() === 'cli') {
echo "Fatal Error: " . $e->getMessage() . "\n";
exit(1);
} else {
echo "<div style='color: red; padding: 20px; margin: 20px; border: 1px solid red;'>Fatal Error: " . htmlspecialchars($e->getMessage()) . "</div>";
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment