How to send an argument when using Artisan::call? - laravel

I'm trying to run an Artisan command with an argument, but I can't figure out how. How do you do it? If I run php artisan video:webmtomp4 N in the terminal, it works fine.
Artisan::call(
'video:webmtomp4',
[$data['videoId']],
new StreamOutput(fopen(storage_path() . '/logs/artisan.log', 'w'))
);
How do you send an argument to the command when using Artisan::call? $data['videoId'] is set, so that is not a problem.

Changing my comment to an answer after checking the documentation. :)
The parameters array should be associative, e.g. ['argument' => $data['videoId']],.

Related

How to get Artisan::call('command:name') output in a variable?

Is it possible to get $output as follows:
$output = Artisan::call('command:name');
I have tried many solutions in different posts but it didn't work on my Laravel 5.2.
You can call the output method on Artisan
Artisan::call('command:name');
$output = Artisan::output();
Make sure you are using one of the available output methods like $this->line('output'); in the actual Artisan command. More info in the docs.
There are several ways to accomplish this, but as your are using such old version of Laravel maybe the best for your case is one that will not require a rewrite when you finally migrate to a newer version. Have you tried perhaps the vanilla PHP methods system, shell_exec and passthru?
system will return just the last line of the command on succes and FALSE on failure
shell_exec will return the entire output but without a way to fetch the output status code
passthru will not return any output instead it will output all on stdout. Although it can be put into a variable using output cache methods (i.e. ob_start and ob_get_contents)
In any case you should call those methods using as argument the CLI version of the command you wish to run:
$output = shell_exec("php artisan command:here");
P.S. If you by any chance have a user input that you want to pass as parameter to a artisan command, make sure you escape it with escapeshellcmd first.

Artisan output not working for route:cache

Why doesn't this code show any output result?
$exitCode = \Artisan::call('route:cache');
$artisanOutput = \Artisan::output();
dd($artisanOutput);
Another artisan console code example shows a result, but this one does not work.
if your app environment is production then you should run
$exitCode = \Artisan::call('route:cache',['--force'=> true]);
$artisanOutput = \Artisan::output();
dd($artisanOutput);
Hope this helps
As per your comment i read. Redirect is what you are trying to achieve.
why not use this instead?
return redirect('adminSettings')->with('success', $successMessage);
And your route should look like this:
Route::get('adminSettings', 'AdminController#adminSettings');
Looking at your original question
$exitCode = \Artisan::call('route:cache');
$artisanOutput = \Artisan::output();
dd($artisanOutput);
Can you try 'php artisan route:cache' from your terminal? What is the output? I am using 5.6 and the output gives me some error. So i think that's the issue.

Laravel - call Artisan command and wait for the result

I'm trying to call in a controller a very time-consuming Artisan command (it executes in 20-90 s ), but I have two problems. First of all it seems like the command does not execute at all (if I return the output it just returns "0").
Secondly the other part (returning the file) does not wait for the command to execute (but it can be related to the first part). Here's my code:
public function returnZip()
{
// just a failsafe, in case if scheduled command did not created the file yet
if( ! file_exists( storage_path( '/app/exports/' . date('Y_m_d') . '.zip' ) ) ){
Artisan::call('maximus:export');
}
return response()->file( storage_path( '/app/exports/' . date('Y_m_d') . '.zip' ) );
}
How can I properly execute the Artisan command from route/controller and wait for it to finish it's task?
EDIT
I tried to debug this problem a little more and found out that the command is not being executed at all when called from a route/controller.
Tried this:
Route::get('/test', function(){
Artisan::call('maximus:export');
return ['ok'];
});
And my command is supposed to create a file:
public function handle()
{
exec('touch /some/path/storage/app/exports/test');
}
When I run this command in terminal, the file is being created, but when I hit the route, it isn't. Any ideas?
Okay, I fired up Laravel and tested it. My command is:
public function handle()
{
exec('touch ' . storage_path(str_random(16) . '.txt'));
}
It works perfectly both in terminal and in a route by calling Artisan::call().
A wild guess: does the www-data user (or whatever user the PHP used by your webserver is running as) have sufficient privilege to write the file?
I'm pretty sure that the artisan command is being handled asynchronously, so it isn't going to wait for the command to finish. Therefore your response is likely to be empty/malformed.
You may want to look into Events and Listeners to ensuring your order of operations is correct (https://laravel.com/docs/5.4/events).
For example, in your maximus:export command you could fire an event immediately after the file has been created.
Example:
Create an event called ZipCreated and a listener called SendZip. Then in your artisan command handler call the event:
event(new ZipCreated($file));
Then link it to a listener in your EventServiceProvider.php:
protected $listen = [
Events\Repository\ZipCreated::class => [
Listeners\Repository\SendZip::class,
],
];
This way ZipCreated will provide SendZip with the zipped file (or a filepath if you want) and SendZip can handle returning the file to the user.
Now whenever the command is run, the creation of the file and the handling of response will always happen in the correct order.
if I return the output it just returns "0"
Let me point out just in case that the call method doesn't return the output of the command, but its exit code ("0" meaning success). Instead, Artisan::output() will return the output.
I'd say check the logs to see what's going on, also check you are in fact useing the Artisan facade. Otherwise, try a debugger or alternatively insert informative dd() statements ;) (the entry point being Illuminate\Foundation\Console\Kernel::call).
try this:
dd(Artisan::output());

Custom artisan commands with multiple 'methods' (in the style of migrate:install etc)

I'm creating a custom artisan command (foo) for my Laravel 4 application. I can see from the userguide how to accept arguments and options, e.g.
php artisan foo argument --option
But what if I want to have a custom artisan command that has many 'methods', in the same style as some built-in artisan commands, e.g. migrate:install?. I want to make something like:
php artisan foo:baz argument --option
What is the recommended way to implement different methods based on the : colon separator? All I've found to try so far is to make an entirely new artisan command for each 'method'. Is there a more efficient way?
You're correct, you do need a new Artisan command (or rather a class) for each method. However all you have to do is register each file in app/Console/Kernel.php, if you decide to change the syntax later than Laravel will pick it up any changes to $signature automatically without you needing to rename any files.
For the Laravel example you mention, migrate, there's a directory with a separate file for each command name (including the one that has no colon):
/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations
migrate -> MigrateCommand.php
migrate:install -> InstallCommand.php
migrate:refresh -> RefreshCommand.php
migrate:reset -> ResetCommand.php
migrate:rollback -> RollbackCommand.php
migrate:status -> StatusCommand.php
If you have code you want to reuse (DRY) note that if you examine the above commands, some of them use traits, e.g. Illuminate\Console\ConfirmableTrait – which contains a confirmToProceed() method which, if it's running in production, will ask the user if they really want to continue.
NB: the Artisan syntax changed in 5.1, from $name (with a rather complicated way of specifying arguments and options) to the much simpler $signature, it's backwards compatible. More info
You just have to set the name:
protected $name = 'foo:baz';

Doctrine 2 CLI commands from within PHP

Hey all. I am writing a program that will transform some data in our database, and then call Doctrine to build YAML files from said Mysql Database structure. I have Doctrine working from within PHP. However I can't figure out how to call the CLI commands from within PHP. Following is the Doctrine 2 CLI command that does what I need.
php ./doctrine orm:convert-mapping --filter="users" --from-database yml ./test
This command works from the Linux command line, but how to I do this same thing via Doctrine objects? I don't want to just use the PHP exec statement to send a command to the shell. I wish to use the Doctrine object model.
Don!:
Apparently this is not a very common programming method. However, I have used Doctrine from PHP by calling it via the PHP EXEC command. I know you said that you would not like to do it this way. However, it actually works quite well. Below is an example of such a solution.
$cmd_string = "php ./doctrine orm:generate-entities --generate-annotations=1 --regenerate-entities=1 $this->entity_file_dir";
$result = array();
exec($cmd_string, &$result);
Hope this helps,
-Don!
I stumbled upon this question when trying to execute a command directly from a PHP script, without using the CLI.
Particularly, I was needing to call orm:ensure-production-settings.
Each Doctrine command has its own class: http://www.doctrine-project.org/api/orm/2.4/namespace-Doctrine.ORM.Tools.Console.Command.html
I solved it the following way:
$entityManager = ...; // Get the entity manager somehow in your application
// Creates the helper set
$helperSet = \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($entityManager);
// Initializes the desired command and sets the helper set
// In your case it should be ConvertMappingCommand instead
$command = new \Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand();
$command->setHelperSet($helperSet);
// Initializes the input
// Alternatives: http://api.symfony.com/2.0/Symfony/Component/Console/Input.html
$input = new \Symfony\Component\Console\Input\ArgvInput(); // Input coming from the CLI arguments
// Initializes the output
// Alternatives: http://api.symfony.com/2.0/Symfony/Component/Console/Output.html
$output = new \Symfony\Component\Console\Output\ConsoleOutput(); // Prints the output in the console
// Runs the command
$command->run($input, $output);
I'm new to Doctrine so I'm not exactly sure how this works, but it does. Any comment is appreciated.

Resources