Laravel provides a static cache utility via Artisan to collapse configuration under config/ into a single file to boost performance. Configuration may be cached using:
php artisan config:cache
When run from terminal, the paths provided may be incorrectly referenced when the application is accessed from the web resulting in application errors.
Solution
Overwrite bootstrap/app.php to use a custom loader. We’ll override a couple methods to bypass cache in CLI SAPI mode (php artisan xx:yy) and opportunistically regenerate the cache whenever remote changes are pushed upstream via git.
Replacing bootstrapper
Create a new file called ApplicationWrapper.php in app/ to provide additional functionality to Illuminate\Foundation\Application:
<?php
namespace App;
use Illuminate\Foundation\Application;
class ApplicationWrapper extends Application {
public function __construct($basePath)
{
if (!isset($_SERVER['SITE_ROOT'])) {
$_SERVER['SITE_ROOT'] = '';
}
parent::__construct($basePath);
}
/**
* Fake configuration cache response for CLI
* as paths will always be different
*
* @return bool
*/
public function configurationIsCached() {
if ($this->runningInConsole()) {
return false;
}
return parent::configurationIsCached();
}
/**
* Emulate \Illuminate\Foundation\Console\ConfigCache\fire()
*
* @return bool
*/
public function doCache() {
if (!$this->runningInConsole()) {
$config = $this->app['config']->all();
$this->files->put(
$this->getCachedConfigPath(), '<?php return '.var_export($config, true).';'.PHP_EOL
);
}
return true;
}
/*
* Override boot to register production config cache
* @return boolean
*/
public function boot()
{
parent::boot();
if ($this->environment() !== "production") {
return;
}
if (!$this->runningInConsole()) {
$app = $this->app;
$this->terminating(function() use ($app) {
$app->configurationIsCached() || $app->doCache();
});
} else {
$path = parent::getCachedConfigPath();
$this->terminating(function() use ($path) {
file_exists($path) && unlink($path);
});
}
}
}
A couple notes:
- Cache is done post-boot so that configuration is properly loaded. Caching is done once at the end of the request to reduce overhead.
- APP_ENV mode is assumed to be “production”; this is controlled by .env.
- artisan config:cache will create, then immediately unlink config.php in favor of generation by the web server
Next, adjust bootstrap/app.php to instantiate a new ApplicationWrapper instance rather than Illuminate\Foundation\Application:
Change:
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
to
$app = new App\ApplicationWrapper(
realpath(__DIR__.'/../')
);
And that’s it! Run php artisan config:clear to have it automatically regenerate during the next page request.
Regenerating Cache with git
Next, create a post-receive hook in your git repository on the server. Create hooks/post-receive if it does not already exist with the following content:
#!/bin/sh
LIVE="/var/www/"
read oldrev newrev refname
if [[ $refname = "refs/heads/master" ]]; then
echo "===== DEPLOYING TO LIVE SITE ====="
unset GIT_DIR
cd $LIVE
./build.sh
echo "===== DONE ====="
fi
And build.sh is a shell script run after every successful git push commit. The following script assumes your Laravel app path is /var/www/laravel-directory and git repository /var/www/git-repository
#!/bin/sh
pushd /var/www/laravel-directory
git pull /var/www/git-repository
# Recompile all class defs into a monolithic file
php artisan optimize --force
php artisan config:clear
Now the next git push will automatically deploy, generate a class loader, and recompile site configuration:
$ git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (5/5), 440 bytes | 0 bytes/s, done. Total 5 (delta 4), reused 0 (delta 0) remote: ===== DEPLOYING TO LIVE SITE ===== remote: /var/www/laravel-production /var/www remote: From ./../git remote: * branch HEAD -> FETCH_HEAD remote: Updating b7b99b8..d4f04a5 remote: Fast-forward remote: config/filesystems.php | 4 ++-- remote: config/view.php | 4 ++-- remote: 2 files changed, 4 insertions(+), 4 deletions(-) remote: Generating optimized class loader remote: Compiling common classes remote: Configuration cache cleared! remote: ===== DONE ===== To ssh://hostineer#hostineer.com@luna.hostineer.com/var/www/git b7b99b8..d4f04a5 master -> master