//Mail Verification File
class EmailVerification extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
protected $user;
public function __construct($user)
{
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('frontend.email.activation')->with([
'email_token' => $this->user->email_token,
]);
}
}
//SendVerificationEmail
class SendVerificationEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
protected $user;
public function __construct($user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$email = new EmailVerification($this->user);
Mail::to($this->user->email)->send($email);
}
}
i am currently working on this simple laravel projects. I am try to make use of queues to implement the user email activation function. and it works fine when i use php artisan queue:work to run it. i now tried to create an task scheduler to do this every five minutes
// The code Here
protected function schedule(Schedule $schedule)
{
$schedule->job(new SendVerificationEmail($user))->everyFiveMinutes();
}
But its returning undefined variable. Is there a mistake in the above, or is there a better way to make Queues run automatically?
Please read: Laravel 5.5 Documentation - Queues#dispatching-jobs
You can't schedule this kind of job, you should dispatch it.
Related
I have two jobs that need to run one after the other. These two jobs are chained, and the entire chain is run twice.
$models = array(1,2);
foreach($models as $model) {
Bus::chain([
new getRecommendations($model),
new processRecommendations($model),
])->dispatch();
}
By my understanding, this is how the queue should run:
getRecommendations(1)
processRecommendations(1)
getRecommendations(2)
processRecommendations(2)
Instead, the queue is running as below:
getRecommendations(1)
getRecommendations(2)
processRecommendations(1)
processRecommendations(2)
How do I get the jobs to run the way I need them? I don't want processRecommendations to wait until all instances of getRecommendations are done before they run.
These are the job classes:
class getRecommendations implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $model;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($model)
{
$this->model = $model;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
// do stuff
}
}
class processRecommendations implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $model;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($model)
{
$this->model = $model;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
// do stuff
}
}
I am using Laravel 5.4 and I want to implement queue in sending emails. I have a function of register as
public function register(CustomerRequest $request)
{
\Log::info("Request Cycle with Queues Begins");
$parameter = 'This is parameter';
dispatch(new SendWelcomeEmail($parameter));
\Log::info("Request Cycle with Queues Ends");
}
and I have created a job inside App\Jobs\SendWelcomeEmail. Which looks like below:
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
#
}
/**
* Execute the job.
*
* #return void
*/
public function handle($parameter)
{
Log::info($parameter);
}
}
Why am I getting error like
Type error: Too few arguments to function App\Jobs\SendWelcomeEmail::handle(), 0 passed and exactly 1 expected in
$parameter not for handle() method, but for its constructor
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $parameter;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($parameter)
{
$this->parameter = $parameter;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Log::info($this->parameter);
}
}
I have a service provider app/Providers/MailchimpServiceProvider.php.
I have added it to providers in config/app.php
Now I would like to use it in a Job:
class SendMail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(Mailchimp $mailchimp)
{
dd($mailchimp);
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
}
}
I think the DI only works in the controllers. How would I use the mailchimp singleton within the job?
You can inject your dependencies in the handle method:
public function handle(Mailchimp $mailchimp)
{
}
I´m trying to create $schedule job in Laravel to read Email with PHP IMAP package. If I go to route, package read email and does all correctly, but need to do this every 5 minutes.
I create a new command class and add this
use Illuminate\Http\Request;
class ReadMail extends Command implements SelfHandling {
protected $name = 'read:mail';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the command.
*
* #return void
*/
public function fire()
{
$request = Request::create($this->option('App\Http\Controllers\MailController#index'), 'GET');
$this->info(app()['Illuminate\Contracts\Http\Kernel']->handle($request));
}
In kernel
protected $commands = [
'App\Console\Commands\ReadMail',
];
protected function schedule(Schedule $schedule)
{
$schedule->call('read:mail')
->everyFiveMinutes();
}
I'm not sure if this code it´is correct, but does not work properly. Any idea about it?
Thank in advance for your help.
UPDATE
I launch this
php artisan read:mail and return
Argument 1 passed to Illuminate\Console\Application::add() must be an instance of Symfony\Component\Console\Command\Command, instance of App\Commands\ReadMail given
The code of ReadMail class
<?php namespace App\Commands;
use App\Commands\Command;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Http\Request;
class ReadMail extends Command implements SelfHandling {
protected $signature = 'read:mail';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the command.
*
* #return void
*/
public function fire()
{
$request = Request::create($this->option('App\Http\Controllers\MailController#index'), 'GET');
$this->info(app()['Illuminate\Contracts\Http\Kernel']->handle($request));
}
}
UPDATE 2: SOLVED - ALL CODE
Kernel
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\Commands\ReadMail',
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('read:mail')
->everyFiveMinutes();
}
}
ReadMail
<?php namespace App\Commands;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Http\Request;
use Illuminate\Console\Command;
use App\Http\Controllers\MailController;
class ReadMail extends Command implements SelfHandling {
protected $name = 'read:mail';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the command.
*
* #return void
*/
public function handle()
{
MailController::index();
}
}
MailController
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use PhpImap\Mailbox as ImapMailbox;
use App\Models\Escalas;
class MailController extends Controller {
public static function index()
{
$mailbox = new ImapMailbox('{imap.gmail.com:993/imap/ssl}INBOX', '', '','');
$mailsIds = $mailbox->searchMailbox('UNSEEN');
if(!$mailsIds) {
die('Mailbox is empty');
}
$mail=[];
foreach ($mailsIds as $index=>$data){
$mail[]=$mailbox->getMail($mailsIds[$index]);
Escalas::insert([
['' => $mail[$index]->textPlain,
'' => $mail[$index]->date,
''=>$mail[$index]->subject,
''=>$mail[$index]->fromName,
''=>$mail[$index]->fromAddress,
''=>$mail[$index]->toString],
]);
}
}
}
Try changing
protected $name = 'read:mail';
with protected $signature= 'read:mail';
in your ReadMail class and then run in Kernel like this
$schedule->command('read:mail')->everyFiveMinutes();
Check whether your scheduled tasks are set up properly (see docs for Laravel 5.0) Make sure you've added a cronjob to trigger Laravel's scheduled commands. To check you cronjobs are running, look for a file like /logs/crond.log. When opening this file, you should see lines showing at what times this ran. This is the command that triggers Laravel's scheduled jobs.
If all that is correct, then try running your command via your terminal on localhost to check the command is all set. This should reveal any problems with the command setup. Your functionality itself seems allright, since you mentioned everything works when triggered via a route.
I'm struggling to understand how I could test a dispatch of a job within another job. I'll provide a code sample.
This is my main job class, we can call it father
final class FatherJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
\Log::info("Hello World, I'm the father.");
dispatch(new ChildJob());
}
}
Then we have the child job
final class ChildJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
\Log::info("I'm the child");
}
}
The test has been set as following
final class JobTest extends TestCase
{
/** #test */
public function it_has_been_dispatched()
{
$this->expectsJobs(ChildJob::class);
dispatch(New FatherJob ());
}
}
This test fails, of course that's the whole point of the question, but why?
I've done some digging and I presume that the problem relies on the call withoutJobs() inside expectsJobs(), it seems that withoutJobs() distrupt the current queue thus it doesn't allow to call the rest of the jobs but maybe I am totally off track.
If this logic is intended, how can I create a test suite that allows me to check if the job within a job has been called?
Thank you in advance.
expectsJobs mock all jobs engine. You can't use dispacth().
$this->expectsJobs(ChildJob::class);
$job = new FatherJob();
$job->handle();