my project in laravel 5.5 and mysql have a start and end date for users to register in my web site
When the time ends on a date determined by the administrator, the following function must be executed in laravel:
public function select()
{
seleccion::create([
'emp_id' => Carbon\Carbon::now()->format('Y-m-d'),
'dst_id' => 'Success',
]);
}
I read the laravel documentation but I do not know what to use
Task Scheduling
commands
event / listeners
Scheduling Queued Jobs
???
those methods do not tell me how to execute a function once on a certain date.
Assuming that there's a single date upon which this function needs to execute, I would simply schedule an Artisan Command
You'd first have to create a command, which you can do by running:
php artisan make:command ExpireRegistrations
Then you'd add your code to the handle() method of the command
Then you would schedule the command to be executed on the date you require, by adding it to App/Console/Kernel.php
See the laravel docs for the scheduling syntax: https://laravel.com/docs/5.5/scheduling#schedule-frequency-options
Lastly, you'll want to ensure that the Laravel
Cron job is set to run on your server by adding this to your Cron Tab:
* * * * * php /path-to-your-project/artisan schedule:
Related
Laravel has Task Scheduling where events, job and commands can be scheduled. I just can't figure out where does it store them? It doesn't look like it stores it in database
Your batch jobs can be stored in a database table, then use the scheduler to execute it.
The function below can be put in app/console/Kernel.php
$schedule->call(function () {
//put your logic here e.g. send verification code to newly
//registered users at 10 pm
})->dailyAt('22:00');
To execute the scheduler, you must specify the name of the command:
protected $commands = [
send:email
];
Then you would call it in terminal as php artisan send:email and keep the terminal process running.
Or you can setup a cron job
I'm looking for a sustainable solution to fetch data every x seconds (let's say 20) and store it in a relational database using PHP. After doing some research I found a few options:
1) Cronjobs (with shell scripts)
See https://askubuntu.com/questions/800/how-to-run-scripts-every-5-seconds for more information. This basically comes down to run a shell script (looping/sleeping)
This doesn't feel right as I could not catch exceptions and/or race conditions might occur. Also, cronjobs itself are not made for this kind of tasks.
2) Web-worker (with queued jobs)
Laravel provides a queue worker that can process new jobs (asynchronously) as they are pushed onto the queue. I could push multiple (say a lot) of jobs to the queue at once which should processed every x seconds consecutively.
This sounds like a more robust solution as I could catch exceptions and make sure the worker is running (using observers). The downside; it's slower and it might be overengineered.
3) Web socket
I could use node.js to run a websocket client like socket.io and implement some kind of timing mechanism to store the data every x seconds.
This solution feels odd as I was taught that sockets are used to push data to clients (realtime), but I have never seen that they were used to insert data.
All help is appreciated.
What you are looking for are artisan commands.
You would start by creating a command:
php artisan make:command FetchData
This creates a FetchData class. In this class you can edit the handle function.
public function handle()
{
//fetch your data here
}
You also need to edit the $signature variable.
protected $signature = 'fetch:data';
The next step is to register the command in the Kernel.php in the Console namespace.
You need to add your newly created FetchData class to the $commands array.
protected $commands = [
Commands\FetchData::class
];
You could now call this command from the console like php artisan fetch:data
After you registered your command in the Kernel.php you can schedule this command.
You start by adding following line to your crontab on your server (type crontab -e)
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
You can now add following command to the schedule function in the Kernel.php:
$schedule->command('fetch:data')->everyThirtyMinutes();
There is no option for a job to run every twenty minutes so in this example I chose thirty minutes. You can check the available options here.
I'm trying to run a Helper function (App\Helpers) on a scheduled timer using Laravel (for testing purposes I have it running once every minute). I'm using Laravel 5.3.
This is my schedule function in my Kernel.php...
protected function schedule(Schedule $schedule)
{
$schedule->call(function()
{
// Calling this function should write a new file with a random number in it.
// I know this works perfectly fine outside of the scheduled task because I
// call it in other places, and it works)
FileEdit::UpdateFile();
})->everyMinute();
}
The issue is that the FileEdit::UpdateFile() part is NOT ever being called by the laravel at the designated time intervals.
Are you running a cron job to execute the schedule command every minute?
https://laravel.com/docs/5.5/scheduling#introduction
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
This Cron will call the Laravel command scheduler every minute. When the schedule:run command is executed, Laravel will evaluate your scheduled tasks and runs the tasks that are due.
Your code looks fine, assuming you have cron configured correctly, this may help you debug your issue https://laravel.com/docs/5.5/scheduling#task-hooks
Still I would double check if your cron is working, and set according to https://laravel.com/docs/5.5/scheduling#introduction
My question is more of a general wondering. I have two commands created using Laravel, let's call them A and B.
Each one of these commands are scheduled with the ->dailyAt($par) method. But the $par parameter comes from a query.
I mean something like this:
protected function schedule(Schedule $schedule)
{
$schedulerTime_commandA = App\Model\CommandsTime::where('id', 1)->first()->time;
$schedulerTime_commandB = App\Model\CommandsTime::where('id', 2)->first()->time;
$schedule->command('A')
->dailyAt($schedulerTime_commandA);
$schedule->command('B')
->dailyAt($schedulerTime_commandB);
}
This is because the superuser wants to schedule the time when those commands will run. My question here is: How Laravel knows this schedule method within the App\Console\Kernel.php file has been changed?
NOTE: I have the following cron entry as Laravel talks about it on the docs.
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
The way Laravel's scheduler system works is it uses a cron job that runs once every minute (that's the * * * * * part in the cron entry: match every minute of every hour of every day of every month of every year).
So every minute, php /path/to/artisan schedule:run >> /dev/null 2>&1 is being run by cron.
When that command runs, it should check the schedule as defined by the schedule() method in the Kernel class when it is run.
So technically, Laravel doesn't know that the schedule has changed, per se. Every minute it should run, hit the schedule() method, which will grab the latest values from the database, and then return the schedule as it is set at that particular minute in time.
Each individual run of the cron knows nothing about the ones that came before it, or the ones that will come after it.
At least that's my understand of the scheduler. I've only spent a little time in the core Laravel Kernel code, but I believe that to what is going on from my own experience.
Hope that helps!
Edit 1
Just confirmed my logic in Laravel's code. Every time the cron script runs, the schedule is rebuilt, so the changes to the schedule in the database will be used the next time the cron entry runs. Laravel doesn't really know that it changed - it just checks every time it runs and uses what it finds.
Specifically, here's the chain through code if it's of interest:
Calling php artisan on the command line will run the artisan file in the project root;
In the artisan file the Application is bootstrapped and a Kernel object is initialized;
When the Kernel class is initialized, the constructor for the Kernel class (Laravel\Lumen\Console\Kernel) calls the defineConsoleSchedule() method on itself;
The defineConsoleSchedule() method initializes a blank Schedule object (Illuminate\Console\Scheduling\Schedule);
The blank Schedule object will be passed to the schedule() method on the Kernel class; and finally
In the schedule() method, which is where you defined your command schedule, your two DB queries will be run, and your two schedule entries will be defined with the values that the DB returns at that moment.
The above actions happen every time the console application bootstraps, which means on every call to php artisan, regardless of what command you wish to run.
When running the schedule:run command specifically, here's what happens next:
After the application bootstraps, the ScheduleRunCommand object (Illuminate\Console\Scheduling\ScheduleRuneCommand) is initialized; and
The fire() method is called on the ScheduleRunCommand object, which runs through all the commands defined on the Schedule object when the application bootstrapped; and
Checks each command to see if that command must be run at that time by calling the isDue() method on the Event (Illuminate\Console\Scheduling\Event) that represents the command; and finally
Each command that needs to be run at that minute, by returning true from isDue() will be run.
I have an event that is fired when I receive certain notifications. I want to Queue the event so that they aren't all fired at the same time but are Queued up as I receive them and then fired after the previous event completes. I want to know the best way to do this.
Edit: Just for anyone in the future, setting up the database Queue driver is very straightforward and simple. You run the php artisan queue:table and change the driver to 'database'. My problem was that my app wasn't recognizing my QUEUE_DRIVER setting in my .env file for some reason.
Laravel 5 has it's own way of dealing with queued jobs, but you can still use the options that were available in Laravel 4. I've personally been curious as to how it all works and just threw together a blank project and ran a couple of queued jobs with a little help from the docs so this may not be a full answer but I hope this helps you on your way.
First you will want to set your config to use the database queue driver, this can be done in config/queue.php or for me it was a matter of going to the .env file and doing this: QUEUE_DRIVER=database.
Then you want to set up the database table to hold the queued jobs, you can do this by running an artisan command: php artisan queue:table this will create the migration so then you need to create the table by running php artisan migrate and then you'll have your jobs table in your DB.
Following that, you'll want to set up a queued job which come in the form of Commands. For example I'll set up a job that writes some text to the log file. You can create jobs or commands using an artisan command, here's what I did to create a command: php artisan make:command WriteToLog --queued. And here's what my command class looks like after adding a little code to get it to write to the log file...
app/Commands/WriteToLog.php
use App\Commands\Command;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldBeQueued;
class WriteToLog extends Command implements SelfHandling, ShouldBeQueued {
use InteractsWithQueue, SerializesModels;
protected $secs;
/**
* Create a new command instance.
*
* #return void
*/
public function __construct($secs)
{
$this->secs = $secs;
}
/**
* Execute the command.
*
* #return void
*/
public function handle()
{
\Log::info('Writing to the log in ' . $this->secs);
}
}
After creating a command, to test it out I wrote a route in my routes file ...
app/Http/routes.php
Route::get('/', function(){
// some time to delay the job
$fiveSecs = \Carbon\Carbon::now()->addSeconds(5);
$tenSecs = \Carbon\Carbon::now()->addSeconds(10);
// adds job to queue
Queue::later($fiveSecs, new App\Commands\WriteToLog('5 secs'));
Queue::later($tenSecs, new App\Commands\WriteToLog('10 secs'));
return 'All done';
});
Before we hit the route we want to listen for any jobs in order to process them, just run php artisan queue:listen then you can go to your browser to the route, after hitting the route in my browser the console shows
$ php artisan queue:listen
Processed: Illuminate\Queue\CallQueuedHandler#call
Processed: Illuminate\Queue\CallQueuedHandler#call
And if I check my log file I see the following:
[2015-05-19 19:25:08] local.INFO: Writing to the log in 5 secs
[2015-05-19 19:25:10] local.INFO: Writing to the log in 10 secs
Not exactly 5 and 10 seconds apart but hopefully you get the idea!
For me this is really just the tip of the iceberg and queued jobs are something very powerful in laravel, I highly recommend checking out the docs here: http://laravel.com/docs/5.0/queues and here: http://laravel.com/docs/5.0/bus
You can also fire events from your queued jobs or queue an event handler, see here for more details: http://laravel.com/docs/5.0/events#queued-event-handlers
Laravel makes queues pretty straightforward, but a bit long to explain fully here. Check out these guides:
If you are using forge, it is really painless:
https://mattstauffer.co/blog/laravel-forge-adding-a-queue-worker-with-beanstalkd
If you aren't using forge, it is still pretty ok: http://fideloper.com/ubuntu-beanstalkd-and-laravel4