Last active
February 10, 2021 10:41
-
-
Save simonhamp/b3e628adcedc0af4ffdf5ae59e9fb6a3 to your computer and use it in GitHub Desktop.
RemoteArtisan: A way to call another Laravel/Lumen application's artisan command from the context of the current application.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace App; | |
| use Dotenv\Dotenv; | |
| use Illuminate\Support\Str; | |
| use Symfony\Component\Process\Process; | |
| use Symfony\Component\Process\Exception\ProcessFailedException; | |
| class RemoteArtisan | |
| { | |
| /** | |
| * Implements an interface similar to Artisan::call. | |
| * | |
| * @param string $path The full path to the remote application's root | |
| * @param string $command The Artisan command to run, e.g. 'vendor:publish' | |
| * @param array $parameters The parameters to pass to the artisan command | |
| * @param string $php The path to the PHP executable | |
| * @return mixed | |
| * @throws ProcessFailedException | |
| */ | |
| public static function call($path, $command, $parameters = [], $php = null) | |
| { | |
| // Prepare parameters for appending | |
| $options = ''; | |
| foreach ($parameters as $name => $value) { | |
| $value = '"'.$value.'"'; | |
| if (is_int($name)) { | |
| $options .= " $value"; | |
| } else { | |
| $value = ($value !== true ? "=$value" : ''); | |
| $options .= " {$name}{$value}"; | |
| } | |
| } | |
| // Swap out the full path to the current PHP executable binary | |
| if (! $php) { | |
| $php = PHP_BINDIR . '/php'; | |
| } | |
| // Load .env for the target app | |
| $env = new Dotenv($path); | |
| $env->overload(); | |
| // Append the artisan command to the path | |
| $artisan = Str::finish($path, '/').'artisan'; | |
| // Build up the final command | |
| $command = "{$php} {$artisan} {$command}{$options}"; | |
| // Run the command in its environment | |
| $process = new Process($command, $path); | |
| $process->run(); | |
| // Restore original environment | |
| $env = new Dotenv(base_path()); | |
| $env->overload(); | |
| // If there was no response | |
| if (! $process->isSuccessful()) { | |
| throw new ProcessFailedException($process); | |
| } | |
| return $process->getOutput(); | |
| } | |
| } |
Author
Author
Simple usage example, from app located at /www/laravel-todo-app/ calling /www/laravel-invoice-app/:
<?php
use App\RemoteArtisan;
// For example, in an event handler when a Todo is completed...
RemoteArtisan::call('/www/laravel-invoice-app/', 'make:invoice', ['INV-0001', '[email protected]', '--send' => true]);Of course, this assumes that the laravel-invoice-app defines and registers an Artisan command with the signature make:invoice and appropriate options.
Tested this with a vanilla php application calling a Lumen application and seems to work quite nicely. Thanks :-)
@simonhamp Thank you very much. This works perfectly
Author
@toxicchili @kakposoe glad that you've found this useful :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For when you want/need to call a specific (local) Laravel/Lumen app's
artisancommand directly from another Laravel/Lumen application. (Of course, if youcomposer requirethe Symfony Process Component, Illuminate Support and PHP DotEnv you can use this from any PHP application to call a local artisan in another app.)I had to create this a few weeks ago because I couldn't find any other way to do this and I finally had reason to pull it out into its own class for reuse, so I thought it was worth sharing.
It mimics the
Artisanfacade, providing acallstatic method. It's differences are that it needs the path to the application you're trying to run an artisan command against and optionally a path to the appropriate PHP binary to use (in case the default doesn't work for you for some reason).I know it's quite rare that you'd ever really need this and I'm sure there must be a nicer solution out there that I'm missing, so I'd welcome comments, feedback and suggestions!