I'm using Laravel 5.2's task scheduler. I need to be able to pass two options to the scheduler, but I'm not sure how to do this.
Here is what I have in my Kernel.php:
protected function schedule(Schedule $schedule)
{
$schedule->command('simple_cron --first_option=10')
->everyMinute();
}
And this in my simple_cron command:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Article;
class SimpleCron extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'simple_cron';
/**
* The console command description.
*
* #var string
*/
protected $description = '';
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$firstOption = $this->option('first_option');
}
}
But this gives me the error:
The "--first_option" option does not exist.
What am I doing wrong?
According to the offical documentation the first thing is that your signature needs to have one/two placeholders for parameters:
protected $signature = 'simple_cron {p1} {p2} {--firstoption=5}';
Here we set a default value of 5 for the option firstoption. If you don't want a default value just write {--firstoption=}
To fetch those parameters in your handle method you can do it like that:
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$p1 = $this->argument('p1'); // should be 10
$p2 = $this->argument('p2'); // should be 20
$option1 = $this->option('firstoption'); // should be 99
//
}
You should then be able to call it like this:
$schedule->command('simple_cron 10 20 --firstoption=99')->daily();
Related
Hi I have a weird issue with passing an option to a command from another command.
Command A
protected $signature = 'foo:bar {--internal}';
Command B
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class FooBaz extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'foo:baz';
/**
* The console command description.
*
* #var string
*/
protected $description = '';
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$this->call('foo:bar --internal');
}
}
Calling foo:baz yields
Command "foo:bar --internal" is not defined.
While calling foo:baz --internal just works. Is this a bug?
According to the documentation, the options can be passed as an arguments
Example:
$this->call('foo:bar', ['internal']);
I am implementing a invoice API system for that I have to implement an automated reminder email on due date, after 3days, after 7days (it is like a API so the email has to be send from login user email to the selected customer)
For this system so far I implemented a checkbox selection which will store the login user, selected customer, due date, day selection for reminder stored the data in database). I have issues in sending emails from different users, adding condition to send email from the due date
console->commands->SendReminderemail.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
Use App\Reminder;
use App\Donor;
use App\Mail\ReminderEmailDigest;
Use Mail;
class SendReminderEmails extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'reminder:emails';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Invoice Reminder Emails';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$pending_Reminders = Reminder::where('status',0)->get();
$data = [];
foreach ($pending_Reminders as $reminder){
$data[$reminder->donor_id][] = $reminder->toArray();
}
foreach($data as $donor_id => $pending_Reminders){
$this->sendEmailToUser($donor_id, $pending_Reminders);
}
// dd($data);
}
private function sendEmailToUser($donor_id, $pending_Reminders){
$user = Donor::find($donor_id);
Mail::to($user)->send(new ReminderEmailDigest($pending_Reminders));
// dd($user);
}
}
App->mail->ReminderEmailDigest
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ReminderEmailDigest extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
private $pending_Reminders;
public function __construct($pending_Reminders)
{
$this->reminders = $pending_Reminders;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('emails.reminder-digest')
->with('pending_Reminders', $this->reminder);
}
}
App->console->kernal
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Console\Commands\SendReminderEmails;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
SendReminderEmails::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('reminder:emails')->everyMinute();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Now only the email working when I enter the reminder:emails command in console
How can i automate the mail?? any related suggestions??
You need to schedule your command.
For that, check how to register your command to schedular and how to set up cron job for schedular to run.
More specifically, you can do something like this:
$schedule->command('reminder:emails')->daily();
Just a note on how you could clean up your code.
$pending_Reminders = Reminder::where('status',0)
->get()
->groupBy('donor_id')
->each(function($reminders, $donor_id) {
$user = Donor::find($donor_id);
Mail::to($user)->send(new ReminderEmailDigest($reminders->toArray()));
});
To set the artisan command to run daily,
app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('reminder:emails')->daily();
}
To get that to run sudo crontab -e
* * * * * cd path/to/project && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
How to empty log files data before adding new contents to it.
Using Monolog for saving all logs inside
storage/app/logs/*
You can use rm command through ssh to remove all logs:
rm storage/logs/laravel-*.log. Use * as wildcard to remove all logs if they have suffixes.
Or you can add custom code within Controller method only for admins of app:
$files = glob('storage/logs/laravel*.log');
foreach($files as $file){
if(file_exists($file)){
unlink($file);
}
}
Or create a console command. Depending on version, below 5.3 use for example:
php artisan make:console logsClear --command=logs:clear
For versions 5.3 and above
php artisan make:command logsClear
add signature within command class if it doesn't exist.
protected $signature = 'logs:clear';
Add your class in Console/Kernel.php, in protected $commands array ( note that your code varies upon customization for your app):
<?php
namespace App\Console;
use App\Console\Commands\logsClear;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Utils\ShareHelper;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
logsClear::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
}
}
You should add then custom code in handle() of logsClear class
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class logsClear extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'logs:clear';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$files = glob('storage/logs/laravel*.log');
foreach($files as $file){
if(file_exists($file)){
unlink($file);
}
}
}
}
Then run php artisan logs:clear command
I am using Laravel 5.0.*, Now I want to implement cron job in my application.
I searched a lot but I get nothing, all the example and video tutorials are related to 5.1 and 5.3 even I search in laravel.com for task scheduling under 5.0 version but it showing nothing
Reference video link : video link
And after using above video reference, I am getting below error in terminal.
[2016-11-02 08:47:06] local.ERROR: exception 'InvalidArgumentException' with message 'There are no commands defined in the "cron" namespace.' in D:\harendar\htdocs\nkbuild\vendor\symfony\console\Symfony\Component\Console\Application.php:501
/app/Console/Kernel.php
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel {
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
'App\Console\Commands\Inspire',
'App\Console\Commands\LogDemo',
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('inspire')
->hourly();
$schedule->command('log:demo')->emailOutputTo('harendar#solutionavenues.com');
}
}
/app/Console/Commands/LogDemo.php
<?php namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class LogDemo extends Command {
/**
* The console command name.
*
* #var string
*/
protected $name = 'log:demo';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Log Demo command.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function fire()
{
\log::info('I was here # ', \Carbon\Carbon::now());
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return [
['example', InputArgument::REQUIRED, 'An example argument.'],
];
}
/**
* Get the console command options.
*
* #return array
*/
protected function getOptions()
{
return [
['example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null],
];
}
}
Hello First you need to run command : php artisan make:console test(command name).
Then you find one test.php command created under app/Console/Commands/test.php .this looks like:
namespace App\Console\Commands;
use Illuminate\Console\Command;
class test extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'test';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
}
}
Currently I'm working on a project where I queue emails to be send. However I wonder what would be the "best way" to run the queue listener. Right now I only know about the nohup way.
However, by using nohup it feels like the queue listener is no part of the application anymore. It's like using the scheduler to make your cronjobs more part of the application.
Are there any other ways to listen the queue and what would be your preference?
Here's what I wrote to achieve this:
app/Console/Commands/QueueProcessListener.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class QueueProcessListener extends Command
{
/**
* The name of the command/process we want to monitor. This string will be used both to check to see if the process
* is currently running and to spawn it (The arguments are appended to it).
*
* #var string
*/
protected $command = 'php artisan queue:listen';
/**
* The arguments to pass to the process when spawning it.
*
* #var string
*/
protected $arguments = '--tries=3';
/**
* The signature of the console command. We use the signature when running it through Artisan: php artisan $signature
*
* #var string
*/
protected $signature = 'queue-process-listener';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Monitor the queue listener process to ensure it is always running.';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
if (!$this->isProcessRunning($this->command)) {
$this->info("Starting queue listener.");
$this->executeShellCommand($this->command, $this->arguments, true);
} else {
$this->info("Queue listener is running.");
}
}
/**
* Execute a shell command, with the provided arguments, and optionally in the background. Commands that are not run
* in the background will return their output/response.
*
* #param $command
* #param string $arguments
* #param bool $background
* #return string
*/
public function executeShellCommand($command, $arguments = '', $background = false)
{
$command = trim($command);
if (!is_string($command) || empty($command)) {
return null;
}
$arguments = trim($arguments);
$cmd = trim($command . ' ' . $arguments) . ($background ? ' > /dev/null 2>/dev/null &' : '');
return shell_exec($cmd);
}
/**
* Check if a process is running using pgrep.
*
* #param $process
* #return bool
*/
public function isProcessRunning($process)
{
$output = $this->executeShellCommand('pgrep -f "' . $process . '"');
return !empty(trim($output));
}
}
app/Console/Kernel.php
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
Commands\QueueProcessListener::class
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// Schedule my process listener to run every 5 minutes.
$schedule->command('queue-process-listener')->everyFiveMinutes();
}
}
The documentation tells you exactly how to achieve this:
https://laravel.com/docs/5.3/queues#supervisor-configuration
I'm not sure what you mean by it not being "part of the application". Crons and background worker processes are a standard part of any scale server architecture. There's nothing wrong with using them.
You also should really avoid doing what Jonathon's answer suggests, which is basically writing your own supervisord in php. What if your server reboots? There are battle-tested solutions for this problem, that have been developed and supported by the linux community for a long time now--you should really use them.