So I am trying to implement a command that notifies all users that are subscribes to an event with command that does an check every day. I was reading Laravel mail docs 7.x so there example is about order system where they send the mail with this peace of code
foreach (['taylor#example.com', 'dries#example.com'] as $recipient) {
Mail::to($recipient)->send(new OrderShipped($order));
}
what as it looks takes the email of of the loop and then send an email toward that adress.
So I made a mail class php artisan make:mail NotifyUserOfEvents
and where I made this code
<?php
namespace App\Mail;
use App\Event;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class NotifyUserOfEvents extends Mailable
{
use Queueable, SerializesModels;
protected $event;
public function __construct(Event $event)
{
$this->event = $event;
}
public function build()
{
return $this->view('mails.NotifyUserOfEvents')
->with([
'name' => $this->event->name,
'date' => $this->event->settings->start_date,
]);
}
}
but when I try to call this class with this function
<?php
namespace App\Console\Commands;
use App\Event;
use App\RegistrationEvents;
use App\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class NotifyUsersForEvents extends Command
{
protected $signature = 'NotifyUsersForEvents';
protected $description = 'Notify the user for the event. test run with -> php artisan schedule:run';
public function __construct()
{
parent::__construct();
}
public function handle()
{
Log::debug('this works every minute');
$events = Event::query()
->with('settings')
->has('settings')
->get();
foreach ($events as $event) {
$week = Carbon::now()->addWeek();
$sixDays = $week->copy()->subDay();
if (Carbon::create($event->settings->date_start)->between($week, $sixDays)) {
$subscriptions = RegistrationEvents::query()
->where('event_id', $event->id)
->get();
foreach ($subscriptions as $subscription) {
var_dump($subscription->user_id);
$user = User::findOrFail($subscription->user_id);
Mail::to($user->email)->send($event);
var_dump($user->email);
}
}
}
}
}
it returns this error: Argument 1 passed to Illuminate\Database\Eloquent\Model::__construct() must be of the type array, object given, called in so do I need to change the way I call the mail class or do I need to add something to the Event Model?
also the event.php
use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Event extends Model implements Mailable
{
use SoftDeletes;
public function settings(){
return $this->hasOne('App\EventSettings', 'event_id');
}
}
You must pass to send function an object of your NotifyUserOfEvents, not an Event object.
Try this:
Mail::to($user->email)->send(new NotifyUserOfEvents($event));
Referring to this line:
Mail::to($user->email)->send(new Event($event));
you are creating a new Event passing to the constructor another Event... you probably never define a constructor that accept as first parameter an Event...
But despite that, what's the sense of doing this? To Mail::send you have to pass a Mailable, not an event, and i'm pretty sure you don't need a new event, so i believe you would want to do something like this:
use App\Mail\NotifyUserOfEvents; // or whatever namespace you have to the mail
Mail::to($user->email)->send(new NotifyUserOfEvents($event));
$user = User::find($id);
$email = $user->email;
if(Helper::isValidEmail($email))
{
Mail::send('emails.applicant_reference',
$emailParameters, function($message) use ($email, $name, $subject){
$message->to($email, $name)
->subject($subject);
});
$applicantName = null;
$subject = " Application received for ".$applicantName;
$emailParameters = ["applicantName" => $applicantName, "proposerName" => $proposerName, "seconderName" => $seconderName];
try
{
Mail::send('emails.application', $emailParameters, function($message) use ($applicantName, $subject){
$message->to(['test#gmail.com','test#gamil.com'], " Test Email Function ")
->subject($subject);
});
} catch (Exception $ex){ Log::error("UserController".$ex->getMessage());
}
Related
I have a laravel project at hand. However, I did not write this project. They gave me a bug to solve. It shows the problem in this file /app/Http/Controllers/Crons/EmailCronJobController.php but as far as I understand, it shows here because sending mail is used here. I have not used such services of Laravel before, so I do not know much. I'm putting the screenshot of the problem and the content of the file below, but if there is something different I need to share for you to understand better, I can share it with you.
enter image description here
EmailCronJobController.php
namespace App\Http\Controllers\Crons;
use App\Http\Controllers\Controller;
use App\Mail\Listener\FirstContentListen;
use App\Mail\Listener\NothingListenedFor3Days;
use App\RawListeningData;
use App\User;
use App\UserPayment;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class EmailCronJobController extends Controller
{
public function __invoke()
{
$this->listeners();
}
private function listeners(){
$this->listenersFirstContentListen();
$this->listenersNothingListenedFor3Days();
}
private function listenersNothingListenedFor3Days(){
$users = User::where([
['role_id','=', 4],
['created_at', '>=', Carbon::now()->subDay(7)->toDateTimeString()],
['created_at', '<', Carbon::now()->subDay(3)->toDateTimeString()]
])->get();
$users = $users->filter(function ($user){
return $user->getFirstListenedContent()==null;
});
/*
foreach ($users as $user){
$email_array = explode('#',$user->email);
$email = $email_array[0].'#etrexio.com';
$user->update(['email'=>$email]);
}*/
foreach ($users as $user){
if($user->getCustomField('nothing_listened_3_days_email_send_date')==null){
Mail::to($user)->send(new NothingListenedFor3Days($user));
$user->setCustomField('nothing_listened_3_days_email_send_date',date('Y-m-d H:i:s'));
}
}
}
private function testEmail(){
$active_user_payments = UserPayment::select('user_id')->where('exprire_date', '>=', Carbon::now()->toDateTimeString())->get();
$active_users_ids = $active_user_payments->map(function ($payments){
return $payments->user_id;
});
$users = User::whereIn('id',$active_users_ids)->get();
dd($users);
}
private function listenersFirstContentListen(){
$last_24_h_listening = RawListeningData::select('user_id')->where('created_at', '>=', Carbon::now()->subDay()->toDateTimeString())->get();
$last_24_h_listening_users = $last_24_h_listening->map(function ($listening){
return $listening->user_id;
})->unique();
$before_24_h_listening = RawListeningData::select('user_id')->whereIn('user_id',$last_24_h_listening_users)->where('created_at', '<', Carbon::now()->subDay()->toDateTimeString())->get();
$before_24_h_listening_users = $before_24_h_listening->map(function ($listening){
return $listening->user_id;
})->unique();
$result = collect($last_24_h_listening_users)->diff(collect($before_24_h_listening_users));
$users = User::whereIn('id',$result)->get();
foreach ($users as $user){
if($user->getCustomField('first_content_listen_email_send_date')==null){
$content = $user->getFirstListenedContent();
if($content!=null){
Mail::to($user)->send(new FirstContentListen($user,$content));
$user->setCustomField('first_content_listen_email_send_date',date('Y-m-d H:i:s'));
}
}
}
}
}
NothingListenedFor3Days.php
namespace App\Mail\Listener;
use App\Course;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class NothingListenedFor3Days extends Mailable
{
use Queueable, SerializesModels;
public $listener;
public $random_contents;
public $fromEmail = 'listener#omnicourse.io';
public $fromName = 'Omnicourse';
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(User $listener)
{
$this->listener = $listener;
$this->random_contents = Course::all()->random(10);
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from($this->fromEmail,$this->fromName)
->view('email.listener.nothing_listened_for_3_days')
->text('email.listener.nothing_listened_for_3_days_plain')
->subject("Let's move ahead together");
}
}
I think it's probably this line:
Mail::to($user)>send(newFirstContentListen($user,$content));
$user in your case it's an object not email. Try to debug it or dd() at several points to see where it get stucks.
Also might want to check this out
Address in mailbox given [] does not comply with RFC 2822, 3.6.2. when email is in a variable
I want to send two different emails with two different view blade files for submitting a single form.
My Controller
<?php
namespace App\Http\Controllers\Frontend;
use App\Mail\quickQuoteMail;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\sysmaster;
use App\Mail\contactEmail;
use Illuminate\Support\Facades\Mail;
class EmailController extends Controller
{
public function contactEmail(Request $request)
{
$data = array(
'ContactPerson'=> $request->FullName,
'ContactEmail'=> $request->Email,
'ContactNumber'=> $request->Number,
'ContactMessage'=> $request->Enquiry,
);
$token = $request->input('g-recaptcha-response');
if(strlen($token)>0)
{
$quickQuoteemail = sysmaster::where('sysm_val_type', 'Contact_Email')->where('sysm_def_id', 'to')->first();
$quickQuote = sysmaster::where('sysm_val_type', 'Contact_Email')->where('sysm_def_id', 'Cc')->first();
if ($quickQuote->sysm_value!=null) {
Mail::to($quickQuoteemail->sysm_value)->cc([$quickQuote->sysm_value, $request->Email])->send(new contactEmail($data));
} else {
Mail::to($quickQuoteemail->sysm_value)->cc($request->Email)->send(new contactEmail($data));
}
return redirect()->back()->with('message','Thank you for contact us.');
}else{
return redirect()->back()->with('message','Please make sure your not a robot');
}
}
}
Mail Function
<?php
namespace App\Mail;
use App\sysmaster;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class contactEmail extends Mailable
{
use Queueable, SerializesModels;
public $data;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$quickQuoteemail = sysmaster::where('sysm_val_type','Contact_Email')->where('sysm_def_id','from')->first();
return $this->from($quickQuoteemail->sysm_value,$this->data['ContactPerson'])
->subject('Contact Us Enquiry')->view('email_contact_quote')->with('data',$this->data);
}
}
I have another view blade file there (contact_email_company) How can I include that view with this function and this UI only will send for the company top one have to go for the only client please help how to do this.
You can use dynamic view name You can pass view name in $data Mail class
Change below in your controller function:
if ($quickQuote->sysm_value!=null) {
$data['view_name'] = 'email_contact_quote';
Mail::to($quickQuoteemail->sysm_value)->cc([$quickQuote->sysm_value, $request->Email])->send(new contactEmail($data));
}
else {
$data['view_name'] = 'contact_email_company';
Mail::to($quickQuoteemail->sysm_value)->cc($request->Email)->send(new contactEmail($data));
}
And in mail class change as below: take view name from $data,
return $this->from($quickQuoteemail->sysm_value,$this->data['ContactPerson'])
->subject('Contact Us Enquiry')->view($this->data['view_name'])->with('data',$this->data);
I would like to send email notifications using the queue.
I have created the queue table and tracked all the documentation related to this topic but the notifications are sent without going through the queue.
In my controller :
Notification::send(User::role('team')->get(), new NewExchangeToCollaboratorNotification($user, $exchange, $firstMessage));
And my notification code is :
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Setting;
class NewExchangeToCollaboratorNotification extends Notification implements ShouldQueue
{
use Queueable;
protected $user; protected $exchange; protected $exchangeMessage; protected $replyToAddress;
public function __construct($user, $exchange, $exchangeMessage)
{
$this->user = $user;
$this->exchange = $exchange;
$this->exchangeMessage = $exchangeMessage;
$this->replyToAddress = Setting::get('MAIL_REPLY_TO_ADDRESS', env('MAIL_FROM_ADDRESS'));
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.exchanges.new',
[
'user' => $this->user,
'exchangeMessage' => $this->exchangeMessage,
'exchange' => $this->exchange
]
) ->subject('New exchange: ' . $this->exchange->title)
->from(env('MAIL_FROM_ADDRESS'))
->replyTo($this->replyToAddress);
}
}
Are the notifications queueable ? Is there something I'm doing wrong ?
Thank you for your answers :)
EDIT :
Add delay does not work too.
$when = now()->addMinutes(10);
Notification::send(User::role('team')->get(), (new NewExchangeToCollaboratorNotification($user, $exchange, $firstMessage))->delay($when));
EDIT 2 :
No failed job
Make sure your .env is:
QUEUE_CONNECTION=database
I try to catch an event, when job is completed
Test code:
class MyTest extends TestCase {
public function testJobsEvents ()
{
Queue::after(function (JobProcessed $event) {
// if ( $job is 'MyJob1' ) then do test
dump($event->job->payload());
$event->job->payload()
});
$response = $this->post('/api/user', [ 'test' => 'data' ], $this->headers);
$response->assertSuccessful($response->isOk());
}
}
method in UserController:
public function userAction (Request $request) {
MyJob1::dispatch($request->toArray());
MyJob2::dispatch($request->toArray());
return response(null, 200);
}
My job:
class Job1 implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $data = [];
public function __construct($data)
{
$this->data= $data;
}
public function handle()
{
// Process uploaded
}
}
I need to check some data after job is complete but I get serialized data from
$event->job->payload() in Queue::after And I don't understand how to check job ?
Well, to test the logic inside handle method you just need to instantiate the job class & invoke the handle method.
public function testJobsEvents()
{
$job = new \App\Jobs\YourJob;
$job->handle();
// Assert the side effect of your job...
}
Remember, a job is just a class after all.
Laravel version ^5 || ^7
Synchronous Dispatching
If you would like to dispatch a job immediately (synchronously), you may use the dispatchNow method. When using this method, the job will not be queued and will be run immediately within the current process:
Job::dispatchNow()
Laravel 8 update
<?php
namespace Tests\Feature;
use App\Jobs\ShipOrder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Bus;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped()
{
Bus::fake();
// Perform order shipping...
// Assert that a job was dispatched...
Bus::assertDispatched(ShipOrder::class);
// Assert a job was not dispatched...
Bus::assertNotDispatched(AnotherJob::class);
}
}
This my generic method, using a route
Route::get('job-tester/{job}', function ($job) {
if(env('APP_ENV') == 'local'){
$j = "\\App\Jobs\\".$job;
$j::dispatch();
}
});
I'm firing event and passing object with array like this:
$event = new App\Events\SendMessage;
$event->msg = [ 'sender_id'=>'191',
'recepient_id'=>'190',
'text'=>'some text',
];
Event::fire($event);
Is it possible to make this call a bit shorter and fire event in one line like this?
Event::fire(new App\Events\SendMessage([
'sender_id'=>'191',
'recepient_id'=>'190',
'text'=>'some text',
]));
You would just need to make sure your event constructor is setup to populate that field.
See: http://laravel.com/docs/5.1/events#defining-events
<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
class SendMessage extends Event
{
use SerializesModels;
public $msg;
public function __construct($msg)
{
$this->msg = $msg;
}
}
Yep. Just pass the data in the __construct()
class SendMessage extends Event
{
protected $data;
public function __construct(array $data)
{
$this->data = $data;
}
}
In your App\Events\SendMessage you need to define a constructor method for example:
namespace App\Events;
class SendMessage {
protected $data = null;
public function __construct(Array $data)
{
$this->data = $data;
}
}
you can fire event like this in laravel
just put the code into your controller
event(new App\Events\EventClassName());
if your Event has parameters then
event(new App\Events\EventClassName(['first' => 'value','second' => 'value']));