I try to send notification via pusher when user submitted new order.
in my CartController where I save data into my orders table I have:
<?php
use App\Events\UserOrdered;
//codes....
public function checkout(Request $request) {
//rest of the code
Auth::user()->orders()->save($order);
event(new UserOrdered($order));
//Cart::clear();
Session::flash('success', 'Thank you. Your order has been received.');
return redirect()->route('ordersindex');
}
when I hit to save my order i will get 404 NOT FOUND on event(new UserOrdered($order));
Here is my Event code:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\Order;
class UserOrdered implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $order;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('order-placed');
}
}
This is my Listener code:
<?php
namespace App\Listeners;
use App\Events\UserOrdered;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendNotification
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param UserOrdered $event
* #return void
*/
public function handle(UserOrdered $event)
{
$pusher->trigger($event, 'order-placed', $order);
}
}
PS: When I try my pusher from pusher website Debug Console i can get notification. Whatever problem is, is from event and listener.
Any idea?
UPDATE
update 2
I managed to get pusher to work (i know is not the best way but it works at least).
here is my listener now:
<?php
namespace App\Listeners;
use App\Events\UserOrdered;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Pusher\Pusher;
use Mail;
class SendNotification
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param UserOrdered $event
* #return void
*/
public function handle(UserOrdered $event)
{
Mail::to($event->order->buyer_email)->send(new UserOrdered($event->order));
$options = array(
'cluster' => 'ap1',
'encrypted' => true
);
$pusher = new Pusher(
'xxxxx', //id
'xxxxx', //key
'xxxx', //secret_key
$options
);
$pusher->trigger('UserOrdered', 'order-placed', $event->order);
}
}
What I need?
Pusher will show notification in admin as new order placed. done
I also want to send 2 emails one to admin to say he/she has new
order, and another to user to say that we received his/her order.
mail function:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Order;
class UserOrdered extends Mailable
{
use Queueable, SerializesModels;
public $order;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('noreply#tester.com')->subject('Your Order recieved!')->markdown('emails.orders');
}
}
Progress: In order to send emails I added Mail::to in my listener as you see above, and added code below to my controller function:
//rest of the code...
Auth::user()->orders()->save($order);
$user = $order->buyer_email;
event(new UserOrdered($order));
Mail::to($request->user)->send(new UserOrdered($order)); //added newly
//Cart::clear();
Session::flash('success', 'Thank you. Your order has been received.');
return redirect()->route('ordersindex');
Problem is:
I get this error
Type error: Argument 1 passed to Illuminate\Mail\PendingMail::send()
must be an instance of Illuminate\Mail\Mailable, instance of
App\Events\UserOrdered given
refers to: Mail::to($event->order->buyer_email)->send(new UserOrdered($event->order));
if I change $event->order at the end of that to something static like $event I will get:
Type error: Argument 1 passed to App\Events\UserOrdered::__construct()
must be an instance of App\Order, instance of App\Events\UserOrdered
given
any idea?
Related
I'm working with one of my Laravel 8 API project's that I've built where a user is able to add a domain to their account. The domain needs to be crawled to obtain expiration dates etc and is available in the user's account.
This process takes some time and so I've extracted the logic that fetches the domain data into a job called DomainExpiryChecker.
When a new domain is added, a job is dispatched, but may not execute straight away, and in some cases the user may even delete the domain before the job runs.
For some reason, even after dispatching my job after a record has been made, I'm getting the following failed job error and I'm not sure what I'm missing:
Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\Models\Domains]
My controller where the job is dispatched resembles the following:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\User;
use App\Models\Domains;
use Carbon\Carbon;
use App\Jobs\DomainExpiryChecker;
class DomainsController extends Controller
{
/**
* Instantiate a new DomainsController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Add a new domain
*
* #param Request $request
* #return Response
*/
public function add(Request $request)
{
$domain = new Domains();
$domain->domain = '';
$domain->crawled = 'pending';
$domain->has_valid_ssl = false;
$domain->user_id = Auth::id();
$domain->save();
// on-demand
if ($domain) {
DomainExpiryChecker::dispatch($domain)->onQueue('on-demand-runs-now');
}
// everything went okay!
return response()->json(['success' => true, 'message' => "Added $domain_name successfully, please allow between 24 and 48 hours for crawling"], 201);
}
}
Whilst my job looks like the following:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use GuzzleHttp\Client;
use App\Models\Settings;
use App\Models\Domains;
use Carbon\Carbon;
class DomainExpiryChecker implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The domain instance.
*/
protected $domain;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($domain)
{
$this->domain = $domain;
}
/**
* Get single domain
*
* #return object
*/
public function getDomain($domain)
{
$domain = Domains::where('id', $domain['id'])
->first();
return $domain;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$updatableDomain = $this->getDomain($this->domain);
if (!$updatableDomain) {
return;
}
// stuff happens here
}
}
What am I missing, I'm sure it's just one thing.
I am passing an array to an event and I am updating the array in the listeners. But I am not getting back the updated array after the event.
This is where I am calling the event:
$roles_permissions = ["val1"];
event(new SeedingRolesPermissions($roles_permissions));
var_dump($roles_permissions);
This is the event class' code. I am simply using the constructor to set up the event's roles_permissions array. I tried passing array by reference as well but didn't help.
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class SeedingRolesPermissions
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $roles_permissions;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($roles_permissions)
{
$this->roles_permissions = $roles_permissions;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
This is the listener to the event:
<?php
namespace Modules\Sales\Listeners;
use App\Events\SeedingRolesPermissions;
use Log;
class AddRolesPermissions
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
}
/**
* Handle the event.
*
* #param SeedingRolesPermissions $event
* #return void
*/
public function handle(SeedingRolesPermissions $event)
{
$event->roles_permissions[] = ["val2"];
}
}
Any help will be greatly appreciated!
I have worked code:
Frontend code
resources/js/components/OnlineWall.vue:
mounted() {
window.Echo.channel('laravel_database_new-payload')
.listen('.new-payload-event', (e) => {
console.info('listen');
console.log(e.payload);
})
}
Event code app/Events/NewPayload.php:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Payload;
class NewPayload implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $payload;
/**
* NewPayload constructor.
* #param Payload $payload
* #return void
*/
public function __construct(Payload $payload)
{
$this->payload = $payload;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('new-payload');
}
/**
* Custom broadcast message name
*
* #return string
*/
public function broadcastAs()
{
return 'new-payload-event';
}
}
If I fire event: NewPayload::dispatch($testNewPayload); all works fine.
But I need to pass integer variable from vue component to laravel event (city_id)
if city_id is identical to city_id of Payload model from event (in $testNewPayload), then fire event . Otherwise don't fire event.
It is possible?
Channel is public, Laravel 7.0
Thank you!
Solved.
mounted() {
window.Echo.channel(`laravel_database_new-payload.${this.city_id}`)
.listen('.new-payload-event', (e) => {
console.info('listen');
console.log(e.payload);
})
}
public function broadcastOn()
{
return new Channel('new-payload.'.$this->payload->city_id);
}
I am deleting a filter which model looks like this:
namespace App;
use App\Events\FilterDelete;
use Illuminate\Database\Eloquent\Model;
class Filter extends Model
{
protected $events = [
'deleting' => FilterDelete::class
];
public function filterGroup()
{
return $this->belongsTo('App\FilterGroup');
}
public function products()
{
return $this->belongsToMany('App\Product', 'product_filters')->withPivot('id', 'quantity', 'price');
}
}
The FilterDelete looks like this:
namespace App\Events;
use App\Filter;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class FilterDelete
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $filter;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Filter $filter)
{
$this->filter = $filter;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
And the listener looks like this:
namespace App\Listeners;
use App\Events\FilterDelete;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class DeleteProductFilter
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param FilterDelete $event
* #return void
*/
public function handle(FilterDelete $event)
{
$event->filter->products()->detach();
}
}
And when I delete a filter the products are not detached and the records stay in the database. No errors are returned, evetywhing seems to be working fine. Can anyone tell me why the products are not detaching ?
I have the following listener setup which sends out email notifications to users upon submitting a form. It works perfectly except when I add implements ShouldQueue it returns an error. I am using Iron.io to fire the events.
If I remove implements ShouldQueue it works fine. However it takes longer for the page to load. What effect does implements ShouldQueue have?
<?php
namespace App\Listeners\Timesheet;
use App\Events\Timesheet\TimesheetCreated;
use App\Repos\Email\EmailTemplateRepoInterface;
use App\Repos\User\UserRepoInterface;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Mail, DbView, Auth;
class EmailTimesheetCreationConfirmation implements ShouldQueue
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct(EmailTemplateRepoInterface $template, UserRepoInterface $user)
{
$this->template = $template;
$this->user = $user;
}
/**
* Handle the event.
*
* #param TimesheetCreated $event
* #return void
*/
public function handle(TimesheetCreated $event)
{
$timesheet = $event->timesheet;
$this->dispatchEmail($timesheet->submitted_by, 1); // send submittor email
$this->dispatchEmail($timesheet->employer_id, 2); // send employer email
$this->dispatchEmail($timesheet->supervisor_id, 3); // send supervisor email
}
/**
*
*
* #param TimesheetCreated $event
* #return void
*/
public function dispatchEmail($id, $templateId)
{
$user = $this->user->getUserNotificationSettingsById($id);
if($user)
{
if($user->notify_create_timesheet)
{
$template = $this->template->findTemplateById(1);
Mail::queue([], [], function ($message) use ($template, $user)
{
$message->to($user->email)
->subject($template->subject)
->setBody(DbView::make($template)->with($user->toArray())->render(), 'text/html');
});
}
}
}
}
The error I get when I use implements ShouldQueue is below:
exception 'ErrorException' with message 'Undefined property: App\Events\Timesheet\TimesheetCreated::$timesheet' in /home/vagrant/Code/App/public/app/Listeners/Timesheet/EmailTimesheetCreationConfirmation.php:33