I am using the Laravel 5.7 and now I am facing the following problem:
I have a cronjobs table which contains many cronjob records. Let's take one for example:
Record one should be repeated every 50 minutes.
I created function getMinutelyCronjobs fetches from DB all the cronjobs whish has to be executed minutely.
I went this way: I created a class in Commands Minutely.php where I get all this cronjobs in the handle() function. When I initialized all the data in Minutely.php class, I cann call this handle() function using $schedule->command('cronjobs:minutely')->everyMinute();.
The problem is, that every cronjob could have different minute_x(recurrence, in my example 50) and then the $schedule->command('cronjobs:minutely')->everyMinute(); should be $schedule->command('cronjobs:minutely')->everyMinute(50);.
here is my getMinutelyCronjobs function :
public static function getMinutelyCronjobs(){
$fields = ['id', 'protocol', 'script', 'minutes_frequency', 'login_user', 'login_password', 'email'];
return Cronjob::select($fields)->where('minutely', 1)
->orderBy('id', 'desc')
->get();
}
How could I implement this ? Thank you for your help.
If you can get by with running the task every hour instead of every 50 minutes, the first answer will work. If you need it to be specifically every 50 minutes, you can try something like this, which should run every 50 minutes instead of every 60.
EDIT:
You didn't give the details about the data you are pulling from your database relating to the jobs, but you should be able to just do something like this to schedule each job.
foreach ($jobs as $job) {
$schedule->command($job->command)->everyMinute()->when(function () {
$now = new \DateTime;
$minutes = floatval($now->format('G'))*60 + floatval($now->format('i'));
return $minutes % $job->minutes == 0;
});
}
everyMinute() instead of use hourlyAt() method
Run the task every hour at 50 mins past the hour
$schedule->command('cronjobs:minutely')->hourlyAt(50);
for more information read this article
Related
I have simple app with simple query to MySQL (select from table without any join). My database records doesn't even reach 1000 record, but the time taken by laravel to get response of a simple select query is over 300-400ms. When i tried in MySQL console, it took no longer than 5ms. Is laravel really that slow? Or something was wrong with my code? Tried using eloquent, query builder, raw query all of them always took over 300ms.
My controller :
public function search(Request $request){
$origin = $request->get('origin');
$destination = $request->get('destination');
$o = explode(",",$origin);
$d = explode(",",$destination);
$response = DB::table('saved_routes')->where([
'from_lat'=>$o[0],
'from_lng'=>$o[1],
'to_lat'=>$d[0],
'to_lng'=>$d[1],
])->get('value');
if($response->isEmpty()){
return response()->json([
['value'=>'Data not found']
]);
}elseif($response[0]->value){
return $response;
}
}
My js api call :
axios.get("/api/savedroutes/search?"+=${origin.lat},${origin.lng}&destination=${destination.lat},${destination.lng}`)
.then(res => {res;})
PS: Im still learning Laravel.
Thanks!
In this case, MySQL has been checked without problems, the query database is not a problem but it takes time to fetch all the data that has been queried on the application => Should use pagination.
You can try using return 1; statement after explode and then after query. Watch the API response time in all 3 scenarios, you will surely get what statement is taking time.
PS: If you want to use full potential of Laravel you should use Eloquent
I'm at the beginner level using the laravel PHP framework. I worked on a blog web application, but I want to do some upgrade.
One of the upgrades is to be able to schedule posts to be published in the future on a selected date and time. Like that of Facebook, or that of rainlab blog in October CMS.
I don't know how to go about this, I would really appreciate it if someone can help me out.
The easiest way to implement delayed posting is to add publish date column (e.g published_at) to posts table and retrieve posts where publish date < now.
Schema:
$table->timestamp('published_at');
Retrieve example:
$posts = Post
::where('published_at', '<', now())
->orderByDesc('published_at')
->paginate(50);
The firstly i will create in database column like
posted_at and show,that columns will be helpful later.
You should create command using
php make:command MyCommand
Then in your app/console/command you will have your command
In app/console/kernel in
protected variable $commands
register your command,put path
Inside your command using Eloquent or Db query get all posts where show=0 and posted_at
$now=date("Y-m-d");
$data=DB::table('test')->where('show',0)->whereRaw("posted_at<$now")->get();
Now you can use each loop and change show=1,something like that:
$date->each(function ($item){
DB::table('test')->where('id',$item->id)->update(['show'=>1]);
});
Last job is put in kernel code which will be run after 1m,try this ->
$schedule->command('myCommand')->everyMinute();
EDIT:
So i checked my code i put changes so your command more or less should looks like this :
$now=date("Y-m-d");
$data=DB::table('test')->where('show_',0)->whereRaw("date(posted_at)<='$now'")->get();
$data->each(function ($item){
DB::table('test')->where('id',$item->id)->update(['show_'=>1]);
Remember to put in header of your command this if you use DB
Use DB;
if Eloquent this but you must change the DB to Model_name
use App\Name_model;
And that is Kernel.php
protected $commands = [
'App\Console\Commands\MyCommand',
];
// and
protected function schedule(Schedule $schedule)
{
$schedule->command('My:Command')->everyMinute();
}
I check if after 1min records in my test database was change ,and show_=0 changed to show_=1 and that's all
I have set cron that runs stock updation for users, Now I have user wise setting if stock updation is set to 'Yes' by user than only that cron should run for particular user.
I have googled it but could not find any solution
Any reference or advice are welcome.
In Laravel it's bad practice to put logic in cron. Use commands and scheduler for that. This problem is common, but another approach that is simple is filter which users need an update in the command.
class UpdateStocks extends Command
{
protected $signature = 'update:stocks';
public function handle()
{
User::where('update_stock', 'Yes')->get()->each(function(User $user) {
// run logic to update the stock
})
}
Put the command in the scheduler.
$schedule->call(new UpdateStocks)->daily();
As explained in the documentation, you can set a cronjob to execute laravel scheduler
I want to run tasks, every wednesday, every two hours starting at 13:00.
I placed the scheduler in Command Kernel for everyhour I want the task to run. But this doesn't work.
// project/app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('inspire')
->wednesdays()
->at('13:00')
->at('15:00')
->at('17:00')
->at('19:00')
->withoutOverlapping();
}
What would be the correct way to set up the schedule for every two hours starting at 13:00 every wednesdays?
I would prefer not using a cronjob expression (* 13,14,15,16,17,18,19,20 * * 3 ) because It's confusing.
My scenario is:
PHP Script 1:
$user = User::find(1);
$user->email = 'email#emailness.com';
$user->save();
PHP Script 2:
$user = User::find(1);
while ($user->email != 'email#emailness.com') {
/** Do stuff **/
}
Now my question is, does the email variable get updated when it's updated from another script? For example, Script 2 runs, while it runs, Script 1 also runs. Will the while statement update and move since the condition isn't true anymore?
I think the simplest way to achieve something like this is to run a query every minute or so checking for updated columns. The alternative would be to make your daemon run some sort of server which gets pinged by a model event.
If you only need to monitor a single user's email, it's easy enough - User::find($id); then sleep(60). If you need to monitor more than one user it gets a bit trickier.
If your model uses timestamps (created_at and updated_at), it's possible to query only for models that have been updated recently. Let's say you want to re-query the database every 60 seconds - what we want to do is query all User models that have an updated_at greater than 60 seconds ago.
I'll use the Carbon class, which is an extension of DateTime included with Laravel, but you can also construct a normal DateTime object or a datetime string manually.
$dt = Carbon\Carbon::now()->subSeconds(60);
$users = User::where('updated_at', '>=', $dt)
->get();
foreach ($users as $user) {
// do something with users that have been updated
}
sleep(60);
You can also replace get() with lists('email') if you only want a flat array of emails of updated users.
There may also be more efficient ways than using sleep(60), maybe using Symfony's Process class, but I'll not get into that here.