Running Laravel Artisan Commands from your Admin Dashboard / GUI

22nd January 2014 | Tags:

Some­times you may wish to run Arti­san com­mands from your admin dash­board /​appli­ca­tion, with­out using the com­mand line. Per­haps you don’t have access to the com­mand line (in which case per­haps it’s time to switch host­ing!), or more likely per­haps you want to man­u­ally run tasks right from your appli­ca­tion. Here’s a quick guide to how you might set that up.

Run­ning a command

To run a com­mand pro­gram­mat­i­cally, you sim­ply do this:

Artisan::call('my-command', array());

The first argu­ment is the name of the com­mand, the sec­ond your options, which I’m going to ignore for brevity.

It’s prob­a­bly more use­ful if you can get a hold of the command’s out­put; you can do this by pass­ing a third argu­ment, which should be a class that imple­ments Symfony\Component\Console\Output\OutputInterface. Per­haps the most use­ful of these classes is StreamOutput. So, for exam­ple, you can write the out­put to a file:

$stream = fopen('log.txt', 'w');
Artisan::call('my-command', array(), new StreamOutput($stream));

Or php://output:

$stream = fopen('php://output', 'w');
Artisan::call('my-command', array(), new StreamOutput($stream));

Armed with this, we can pro­ceed with the admin interface.

The Admin Interface

Now to set up a route for the main admin page.

The first thing we prob­a­bly want to do is set up a white-​list of com­mands you’re per­mit­ted to run from the back-​end:

// @file app/config/commands.php
return array(
    /**
    * An array of commands which are available to run from the admin area.
    */
    'whitelist' => array(
        'my-command',
        'another-command',
        'do-something-else',
    ),
);

You’ll notice the white-​list just con­tains the com­mands’ names; we can get the descrip­tions as defined in the Com­mand classes themselves.

Here’s an exam­ple route:

use Symfony\Component\Console\Output\StreamOutput,
use Symfony\Component\Console\Descriptor\ApplicationDescription;

Route::get('/commands', function()
{   
        $app = App::make('app');

        $app->loadDeferredProviders();

        $console_app = \Illuminate\Console\Application::start($app);

        $description = new ApplicationDescription($console_app, null);

        foreach ($description->getCommands() as $command) {
            if (in_array($command->getName(), Config::get('commands.whitelist'))) {
                $commands[$command->getName()] = $command->getDescription();
            }
        }

        return View::make('commands.index', array('commands' => $commands));
});

This code explained:

  1. We get a ref­er­ence to the Lar­avel appli­ca­tion from the IoC container
  2. We load deferred providers — with­out this, we won’t have access to our own commands
  3. We grab a Con­sole application
  4. We get an instance of Symfony\Component\Console\Descriptor\ApplicationDescription, which will pro­vide us with infor­ma­tion about the commands
  5. We take a sub­set of the com­mands — cross-​referencing them against the white-​list — and pass their names and descrip­tions to the view.

Now the view:

<html>
<body>
<ul id="commands">
    @foreach ($commands as $name => $description)
    <li><a href="/commands/run/{{ $name }}">{{ $description }}</a></li>
    @endforeach
</ul>

<div id="output">

</div>
</body>
</html>

This is sim­ply a list of links and an empty DIV to hold the out­put, which we’ll pop­u­late (by run­ning the appro­pri­ate com­mand) via AJAX.

The Javascript:

$('#commands li a').click(function(){
    $('#output').html('<p>Running...</p>');
    $('#output').load($(this).attr('href'));
    return false;
});

Finally, the route to actu­ally run the command:

Route::get('/commands/run/{command}', function($command)
{
    print '<pre>';
    $stream = fopen('php://output', 'w');
    Artisan::call($command, array(), new StreamOutput($stream));
    print '</pre>';
    print '<p>DONE</p>';
});

It’s a sim­plis­tic exam­ple, with some cru­cial omis­sions — argu­ments /​options and secu­rity — but it’s a start­ing point.

Comments

    Hello!

    i appreciate the article about the laravel commands above, i was struggling to get contents of the commands and store them on database so as i can use it somewhere later, i wounder if you ever did such a thing, for me the scenario was to call php artisan routes and store the URI to database but i tried i failed i would appreciate if you will demonstrate it also.

    Regards

    26th January 2016
    Joram Kimata
    Joram Kimata

    Thanks for the helpful Post!

    Hint:
    It’s possible to use

    Artisan::output()

    to get the Ouput of the last called Artisan command.
    (Laravel 5.2)

    Greeting
    Sabine

    29th January 2016
    sabine
    sabine

Links and images are allowed, but please note that rel="nofollow" will be automactically appended to any links.