Skip to content

Instantly share code, notes, and snippets.

@a-h-abid
Created February 4, 2026 19:31
Show Gist options
  • Select an option

  • Save a-h-abid/c67c98fba4d3492268346a6e0c0e787c to your computer and use it in GitHub Desktop.

Select an option

Save a-h-abid/c67c98fba4d3492268346a6e0c0e787c to your computer and use it in GitHub Desktop.
Preload script for Laravel application. Made based on version 12. Generated with help from Claude AI.
<?php
/**
* Laravel Framework Preloader
*
* Preloads Laravel framework files for improved performance.
* Uses a custom class map loader to avoid triggering Composer's autoload files
* which can contain anonymous classes that cause preload warnings.
*
* Place this file in your project root and configure in php.ini:
* opcache.preload=/path/to/your/project/preload.php
* opcache.preload_user=www-data (or your web server user)
*/
if (!function_exists('opcache_compile_file') || !ini_get('opcache.enable')) {
return;
}
$preloadedClasses = 0;
$skippedClasses = 0;
$startTime = microtime(true);
// Load only the Composer class map (not the full autoloader with file includes)
$classMapFile = __DIR__ . '/vendor/composer/autoload_classmap.php';
if (!file_exists($classMapFile)) {
error_log('Laravel Preloader: Class map not found. Run "composer dump-autoload --optimize"');
return;
}
$classMap = require $classMapFile;
// Load essential function files that some classes depend on
$functionFiles = [
__DIR__ . '/vendor/symfony/deprecation-contracts/function.php',
__DIR__ . '/vendor/symfony/polyfill-php80/bootstrap.php',
__DIR__ . '/vendor/symfony/polyfill-php83/bootstrap.php',
__DIR__ . '/vendor/symfony/polyfill-mbstring/bootstrap.php',
__DIR__ . '/vendor/symfony/polyfill-ctype/bootstrap.php',
__DIR__ . '/vendor/symfony/polyfill-intl-grapheme/bootstrap.php',
__DIR__ . '/vendor/symfony/polyfill-intl-normalizer/bootstrap.php',
];
foreach ($functionFiles as $file) {
if (file_exists($file)) {
require_once $file;
}
}
// Register a minimal autoloader that uses only the class map
spl_autoload_register(function (string $class) use ($classMap): void {
if (isset($classMap[$class])) {
require $classMap[$class];
}
});
// Only preload namespaces that are safe and commonly used by Laravel
$preloadPrefixes = [
// PSR interfaces (safe, no dependencies)
'Psr\\Container\\',
'Psr\\Log\\',
'Psr\\SimpleCache\\',
'Psr\\Http\\Message\\',
'Psr\\EventDispatcher\\',
'Psr\\Clock\\',
// Symfony contracts and polyfills (safe base classes)
'Symfony\\Polyfill\\',
'Symfony\\Contracts\\',
// Symfony components used by Laravel (order matters - dependencies first)
'Symfony\\Component\\Clock\\',
'Symfony\\Component\\Uid\\',
'Symfony\\Component\\HttpFoundation\\',
'Symfony\\Component\\Finder\\',
'Symfony\\Component\\Mime\\',
'Symfony\\Component\\VarDumper\\',
'Symfony\\Component\\ErrorHandler\\',
'Symfony\\Component\\Translation\\',
'Symfony\\Component\\CssSelector\\',
'Symfony\\Component\\Process\\',
'Symfony\\Component\\Mailer\\',
'Symfony\\Component\\String\\',
// Carbon date library
'Carbon\\',
// Monolog logging
'Monolog\\',
// Egulias email validator
'Egulias\\EmailValidator\\',
// Laravel contracts and support (base classes/traits - must be first)
'Illuminate\\Contracts\\',
'Illuminate\\Support\\',
// Laravel core components
'Illuminate\\Auth\\',
'Illuminate\\Bus\\',
'Illuminate\\Cache\\',
'Illuminate\\Collections\\',
'Illuminate\\Config\\',
'Illuminate\\Container\\',
'Illuminate\\Cookie\\',
'Illuminate\\Database\\',
'Illuminate\\Encryption\\',
'Illuminate\\Events\\',
'Illuminate\\Filesystem\\',
'Illuminate\\Foundation\\',
'Illuminate\\Hashing\\',
'Illuminate\\Http\\',
'Illuminate\\Log\\',
'Illuminate\\Macroable\\',
'Illuminate\\Pagination\\',
'Illuminate\\Pipeline\\',
'Illuminate\\Queue\\',
'Illuminate\\Redis\\',
'Illuminate\\Routing\\',
'Illuminate\\Translation\\',
'Illuminate\\Validation\\',
'Illuminate\\View\\',
];
// Patterns to exclude (class names) - be aggressive to avoid dependency issues
$excludePatterns = [
'/Test$/',
'/Tests?\\\\/',
'/Testing\\\\/',
'/Fixture/',
'/Mock/',
'/Stub/',
'/Example/',
'/Benchmark/',
'/Command$/', // Skip console commands (often have complex dependencies)
'/Console\\\\/', // Skip console namespace entirely
'/DependencyInjection\\\\/', // Skip Symfony DI-related classes
'/CompilerPass/', // Skip compiler passes
'/ServiceProvider$/', // Skip service providers (loaded by Laravel at runtime)
'/Artisan/', // Skip artisan-related classes
'/PHPStan\\\\/', // Skip PHPStan integration classes
'/Carbon\\\\Doctrine\\\\/', // Skip Carbon Doctrine integration (requires doctrine/dbal)
'/Carbon\\\\PHPStan\\\\/', // Skip Carbon PHPStan integration
'/Carbon\\\\Laravel\\\\/', // Skip Carbon Laravel service provider
'/@anonymous/', // Skip anonymous classes
'/Loader$/', // Skip file loaders (often have optional dependencies)
'/Generator$/', // Skip generators
'/Dumper$/', // Skip dumpers
'/Symfony\\\\Component\\\\HttpFoundation\\\\Session\\\\Storage\\\\Handler\\\\IdentityMarshaller/', // Requires symfony/cache
'/Symfony\\\\Component\\\\Mailer\\\\Bridge\\\\/', // Skip mailer bridges (optional dependencies)
'/Symfony\\\\Component\\\\Translation\\\\Bridge\\\\/', // Skip translation bridges
'/Symfony\\\\Component\\\\Translation\\\\Loader\\\\/', // Skip translation loaders (optional deps)
'/Symfony\\\\Component\\\\Translation\\\\Dumper\\\\/', // Skip translation dumpers
'/Symfony\\\\Component\\\\Translation\\\\Extractor\\\\/', // Skip translation extractors
'/Symfony\\\\Component\\\\Translation\\\\Writer\\\\/', // Skip translation writers
'/Monolog\\\\Handler\\\\/', // Skip Monolog handlers (many have optional dependencies)
'/Monolog\\\\Formatter\\\\/', // Skip Monolog formatters
'/Monolog\\\\Processor\\\\/', // Skip Monolog processors
];
/**
* Check if a class name should be excluded
*/
function shouldExcludeClass(string $className, array $excludePatterns): bool
{
foreach ($excludePatterns as $pattern) {
if (preg_match($pattern, $className)) {
return true;
}
}
return false;
}
/**
* Check if a class name matches any of the prefixes we want to preload
*/
function matchesPrefix(string $className, array $prefixes): bool
{
foreach ($prefixes as $prefix) {
if (str_starts_with($className, $prefix)) {
return true;
}
}
return false;
}
/**
* Safely preload a class using the autoloader
* This ensures all dependencies (parent classes, traits, interfaces) are loaded first
*/
function preloadClass(string $className): bool
{
if (class_exists($className, true) || interface_exists($className, true) || trait_exists($className, true)) {
return true;
}
return false;
}
// Get Composer's class map
$composerLoader = require __DIR__ . '/vendor/composer/autoload_classmap.php';
$classMap = $composerLoader;
// If class map is empty, we need to use the optimized autoloader
// Run: composer dump-autoload --optimize
if (empty($classMap)) {
error_log('Laravel Preloader: Class map is empty. Run "composer dump-autoload --optimize" for best results.');
}
// Collect classes to preload, organized by prefix for proper ordering
$classesToPreload = [];
foreach ($classMap as $className => $filePath) {
if (matchesPrefix($className, $preloadPrefixes) && !shouldExcludeClass($className, $excludePatterns)) {
$classesToPreload[$className] = $filePath;
}
}
// Sort classes to ensure dependencies are loaded first
// Classes with fewer namespace segments (more generic) should load first
uksort($classesToPreload, function ($a, $b) use ($preloadPrefixes) {
// First, sort by prefix order (dependencies first)
$aIndex = PHP_INT_MAX;
$bIndex = PHP_INT_MAX;
foreach ($preloadPrefixes as $index => $prefix) {
if (str_starts_with($a, $prefix) && $aIndex === PHP_INT_MAX) {
$aIndex = $index;
}
if (str_starts_with($b, $prefix) && $bIndex === PHP_INT_MAX) {
$bIndex = $index;
}
}
if ($aIndex !== $bIndex) {
return $aIndex - $bIndex;
}
// Then sort by namespace depth (shallower first - base classes before derived)
$aDepth = substr_count($a, '\\');
$bDepth = substr_count($b, '\\');
if ($aDepth !== $bDepth) {
return $aDepth - $bDepth;
}
// Finally, alphabetical for consistency
return strcmp($a, $b);
});
$h = fopen(__DIR__ . '/storage/app/preloaded-files.txt', 'w');
// Preload classes using the autoloader (ensures proper dependency resolution)
foreach ($classesToPreload as $className => $filePath) {
try {
if (preloadClass($className)) {
fwrite($h, $filePath . PHP_EOL);
$preloadedClasses++;
} else {
$skippedClasses++;
}
} catch (Throwable $e) {
$skippedClasses++;
// Only log actual errors, not "class not found" which is expected for some edge cases
if (!str_contains($e->getMessage(), 'not found')) {
error_log("Preload warning for {$className}: " . $e->getMessage());
}
}
}
fclose($h);
$endTime = microtime(true);
$duration = round(($endTime - $startTime) * 1000, 2);
$peakMemory = memory_get_peak_usage(true);
/**
* Format bytes into human-readable form
*/
function formatBytes(int $bytes, int $precision = 2): string
{
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, $precision) . ' ' . $units[$pow];
}
// Log preload statistics (only visible during preload process)
error_log(sprintf(
'Laravel Preloader: Preloaded %d classes (%d skipped) in %s ms, peak memory: %s',
$preloadedClasses,
$skippedClasses,
$duration,
formatBytes($peakMemory)
));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment