Maintenance Mode without using Artisan?

Solution 1:

You can just call artisan from your application:

Artisan::call('down');

Artisan::call('up');

But since you'll not have access to get your app up because it's down. You can create the functionality yourself:

A route for shut it down, user must be authenticated to do this:

Route::group(array('before' => 'auth'), function()
{

    Route::get('shut/the/application/down', function() 
    {
        touch(storage_path().'/meta/my.down');
    });

});

A route to bring it back up:

Route::get('bring/the/application/back/up', function() 
{
    @unlink(storage_path().'/meta/my.down');
});

A filter to check if it's up:

Route::filter('applicationIsUp', function()
{
    if (file_exists($this['path.storage'].'/meta/my.down'))
    {
        return Redirect::to('site/is/down');
    }
});

A route to bring it back up:

Route::get('bring/the/application/back/up', function() 
{
    @unlink(storage_path().'/meta/my.down');
});

A route to show a pretty view when your site is down

Route::get('site/is/down', function() 
{
    return View::make('views.site.down');
});

Solution 2:

Laravel 5

Downfile is in storage/framework/down - thanks @ruuter. It needs to be populated with JSON:

{"time": UNIXTS, "message": "", "retry": ""}

Not sure where this message is used, but if you need to customize the message for Maintenance page, create resources/views/errors/503.blade.php as you like.

Laravel 4.1 and below

Taking a look at the DownCommand class for Artisan, it seems to create a new file within the app/storage/meta folder.

Heres the DownCommand fire method.

public function fire()
{
    touch($this->laravel['path.storage'].'/meta/down');

    $this->comment('Application is now in maintenance mode.');
}

And the corresponding UpCommand fire method.

public function fire()
{
    @unlink($this->laravel['path.storage'].'/meta/down');

    $this->info('Application is now live.');
}

These files are located in vendor/laravel/framework/src/Illuminate/Foundation/Console.

It specifically creates a file called down in app/storage/meta.

You could create an authorized route / controller action to replicate these commands.

Note Sjaak Trekhaa's comment below, that is the method I would use now that I've been reminded of it!

Solution 3:

Laravel 4

Just wanted to put this out there for everyone on the web, all php artisan down does is touch (create) an empty file in the app/storage/meta directory called 'down'. If this file exists, then the application is in maintenance mode. That's all there is to it:

// From vendor\laravel\framework\src\Illuminate\Foundation\Application.php

public function isDownForMaintenance()
{
    return file_exists($this['config']['app.manifest'].'/down');
}

So if you can upload files, all you need to do is upload an empty file named 'down' to app/storage/meta.


Laravel 5:

Down is located in storage/framework/down

Thanks ruuter.

Solution 4:

The real correct answer to question is above provided by Antonio.

You can just call artisan from your application:

Artisan::call('down');

Artisan::call('up');

Laravel 5+

Since middleware(s) were introduced in Laravel 5, I will cover how I do it in Laravel 5.3 application.

Create brand new middleware

First lets create new middleware $php artisan make:middleware CheckForMaintenanceMode

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;

class CheckForMaintenanceMode
{
    protected $app;

    public function __construct(Application $app)
    {
        $this->app = $app;
    }

    public function handle($request, Closure $next)
    {
        if ($this->app->isDownForMaintenance() && !$this->isBackendRequest($request)) {
            $data = json_decode(file_get_contents($this->app->storagePath() . '/framework/down'), true);

            throw new MaintenanceModeException($data['time'], $data['retry'], $data['message']);
        }

        return $next($request);
    }

    private function isBackendRequest($request)
    {
        return ($request->is('admin/*') or $request->is('login'));
    }
}

Note: function isBackendRequest() which returns true or false if we are either in admin prefix (true) or trying to login (true) or anything else (false)

replace global middleware

Open up App/Http/Kernel.php and rewrite foundations middleware with our new middleware

protected $middleware = [
    \App\Http\Middleware\CheckForMaintenanceMode::class,
];

If application is in maintenance mode (down) we can still access login page or any admin/* page.

Route::group(['middleware' => 'auth', 'prefix' => 'admin'], function () { 
    //admin routes
});