I've a problem that I'm trying to fix all day now. I've followed
this tutorial. The goal is to make a chat with Laravel echo, vue.js and pusher.
I've done everything exactly like the tutorial but for some reason I do not receive any events in my pusher console. Only the connection shows up:
But no events. The event that I fire looks like this:
<?php
namespace App\Events;
use App\Message;
use App\User;
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;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* #var
*/
public $user;
/**
* #var
*/
public $message;
/**
* MessageSent constructor.
* #param User $user
* #param Message $message
*/
public function __construct(User $user, Message $message)
{
$this->user = $user;
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('chat');
}
}
I fire the event like this:
broadcast(new MessageSent($user, $message))->toOthers();
When I dd('test'); like this in my MessageSent event class:
public function broadcastOn()
{
dd('test');
return new PrivateChannel('chat');
}
The dd('test'); shows up in my network tab.
I'm using Laravel 5.4 and Vue.js 2.0 with Homestead. What could be going on here?!
It looks likes you are following this tutorial. I also had a hard time to figure it out. I already answered here. Can you please check it out?
I worked on typing feature in the chat system. Please take a look at the code on GitHub.
Let me know if you have any questions. Thanks :)
By the looks of your debug console screenshot you are never managing to subscribe to any channels, have you set up the necessary authentication for the private channel subscription?
The complete demo code for the tutorial that you've been following is on github so you might want to take a look at that and see where yours differs.
If you are on Laravel 5.4, make sure you have set-up the channel authentication.
For example, in your routes/channels.php file, there should be something like this:
Broadcast::channel('chat', function ($user) {
return true; // change this to your authentication logic
});
Related
In my multi-server application I use laravel's Queueing system in order to run background jobs. Sometimes in my logic I want to make my job to throw an exception so I can log it via a sentry using the laravel library that offers.
So in my job:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use App\Model\Etable\User;
use App\Model\User;
class MyJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
/**
* #var int
*/
private $user_id;
/**
* #param int $user The user that has opted or deopted for newsletter consent
*/
public function __construct(int $id)
{
$this->user_id = $user_id;
}
public function handle(): void
{
/**
* #var User
*/
$user=User::useWritePdo()->find($this->user_id);
if(empty($user)){
throw new \Exception("No such a user with user id: {$this->user_id}");
}
// Rest of logic here
}
}
Once the exception is thrown, I will to be logged into sentry but also it will keep on respawning as laravel's logic for jobs is supposed to do so.
In my case I think it as waste of resources to keep an respawning the MyJob in case that the user does not exist no value to keep on spawning because the logic itself cannot be performed in case that no user exists. On the other hand on any other error I want my job to keep on retrying till be able to sucessfully run again.
So how I can make my job not to respawn on specific errors? Even better would be as well if I can use the default logging method that laravel ofers in order to arbitary log an error into sentry as well via a sentry dedicated channel.
The best and easier approach is once the code failt to check how many times has already be executed:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use App\Model\Etable\User;
use App\Model\User;
class MyJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
/**
* #var int
*/
private $user_id;
/**
* #param int $user The user that has opted or deopted for newsletter consent
*/
public function __construct(int $id)
{
$this->user_id = $user_id;
}
public function handle(): void
{
/**
* #var User
*/
$user=User::useWritePdo()->find($this->user_id);
if(empty($user)){
if ($this->attempts() > 1) {
return;
}
throw new \Exception("No such a user with user id: {$this->user_id}");
}
// Rest of logic here
}
}
This is being achieved via the:
if ($this->attempts() > 1) {
return;
}
So you throw once the exception, the exception is being logged into the Sentry and then on the second time that will be executed it will just exit and never respawn.
Please note that failed jobs won't be re-run unless you explicitly run
php artisan queue:failed
You can throw an exception and handle it in boot method of AppServiceProvider, deleting the job to avoid its further re-tries. See documentation on how to do it.
I'm working on a project using Laravel where I want to be able to send an email when it is scheduled to send.
So far I've only found solutions to send a mail through a Route but I want to be able to send the mail when cron activates my self made command. I've already made a view of the mail that should be sent and made a page sendMail with php artisan make:mail sendMail that returns the mail view.
sendMail.php
<?php
namespace App\Mail;
use Illuminate\Support\Facades\DB;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class sendMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct()
{
$winnersposts = DB::select('select post_id from winners group by post_id');
$posts = DB::select('select * from posts ');
$this->winnerposts =$winnersposts;
$this->posts=$posts;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this ->from('ivanrompa#gmail.com')
->view('emails.template');
}
}
mailAdmin.php
public function handle()
{
}
My command handle is still empty but I previously tried to implement to logic from my controller above in my command but it didn't work.
Am I writing the wrong code and is that the reason it just doesn't work or should I approach it in a different way? It is maybe good to know that I am still learning Laravel and I have never sent an email before through code. Any tips or solutions are welcome.
Assuming you have set your email configuration correctly.
Add this in your mailAdmin.php
use Mail;
use App\Mail\sendMail
public function handle()
{
Mail::to('recipient#gmail.com')->send(new sendMail);
}
Then run the command
I was following a tutorial to get Laravel to broadcast real-time but got stuck after just a few minutes of following along. Laravel throws the following message to me "Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, integer given, called in /home/vagrant/code/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php on line 775"
I've tried to redo the tutorial several times to make sure that I didn't miss a thing but the problem is still the same after several tries.
Even checking the stack trace and documentation didn't give me any clue.
I've uncommented the following line in config/app.php:
App\Providers\BroadcastServiceProvider::class,
I've added the following lines to App\Providers\EventServiceProvider:
use App\Events\RideCreated;
use App\Listeners\RideCreatedListener;
and the following after protected $listen = [ in the same file
RideCreated::class => [
RideCreatedListener::class,
],
this is the setup of the route used for testing (web.php):
Route::get('/test', function(){
event(new RideCreated());
return "test";
});
and this is how RideCreated.php looks like:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class RideCreated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('RideCreated');
}
}
the listener (RideCreatedListener.php) looks like this:
<?php
namespace App\Listeners;
use App\Events\RideCreated;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class RideCreatedListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param RideCreated $event
* #return void
*/
public function handle(RideCreated $event)
{
//
}
}
I expected when visiting the /test rout to see test on screen but actually got the error message displayed.
my first thought was that the ShouldBroadcast implementation in RideCreated.php somehow causes the problem since removing implement ShouldBroadcast makes the error disappear. the only problem is that removing it is no option since it's needed for Pusher to work.
This may sound strange, but we have been resolving this issue f2f. My answer is just for other people that might read this.
It turned out that the queue was not configured such that a default queue could be resolved by Laravel. The error was fixed by adding the $bradcastQueue property to the RideCreated class. See Broadcast Queue
I know how to use ShouldQueue my question is about why does it work the way it does.
I need to edit how my new Job is stored in the database, and therefore am digging through Laravel's internals.
The job I want to edit is launched from the following event listener:
<?php
namespace App\Listeners;
use App\Events\NewMail;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Jobs\SendEmail;
use Carbon\Carbon;
class NewMailListener implements ShouldQueue
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param NewMail $event
* #return void
*/
public function handle(NewMail $event)
{
$addressee = $event->user->name;
$address = $event->user->email;
$type = "NewMail";
$job = (new SendEmail($type,$addressee,$address))->delay(Carbon::now()->addMinutes(10));
dispatch($job);
}
}
What I don't understand is how the ShouldQueue magic works, because in the source code it appears to do nothing.
<?php
namespace Illuminate\Contracts\Queue;
interface ShouldQueue
{
//
}
I understand it is a contract but it's not defining anything... so what it is doing exactly? Is there some auto-loading happening from the namespace?
I wasn't sure what an interface was exactly, so I looked at this: PHP Docs: Interfaces and came away with the impression that even if it is for decoupling, and interface should be defining something, which I don't see in ShouldQueue.
The top comment on that PHP docs page says this:
An INTERFACE is provided so you can describe a set of functions and
then hide the final implementation of those functions in an
implementing class. This allows you to change the IMPLEMENTATION of
those functions without changing how you use it.
But where is this description of functions here?
PS - I know this interface/contract is being used to queue the event listener itself, not the job that I want to edit. But I'm hoping understanding how the queue interacts with the event listener will better inform me as to how it works for the jobs.
Internally Laravel checks if Job or Mailable or Notification etc implements ShouldQueue interface. For example:
if ($job instanceof ShouldQueue) {
https://github.com/laravel/framework/blob/5.5/src/Illuminate/Console/Scheduling/Schedule.php#L86
So, I'm trying to log in a user on Laravel 5.5 using SSO. I'm using a library and it works fine, data come back correctly. However when on Listener I try to Auth::login or any Session data, it's not saved. Sessions works fine from any other point of the app, but not in Listener Events.
<?php
namespace App\Listeners;
use App\User;
use Illuminate\Support\Facades\Auth;
use \Aacotroneo\Saml2\Events\Saml2LoginEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class AuthListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param object $event
* #return void
*/
public function handle(Saml2LoginEvent $event)
{
$messageId = $event->getSaml2Auth()->getLastMessageId();
// your own code preventing reuse of a $messageId to stop replay attacks
$user = $event->getSaml2User();
$attributes = $user->getAttributes();
$id = $attributes['id'];
$laravelUser = User::where('id', $id)->first();
\Session::push('name', 'test');
Auth::login($laravelUser, true);
}
}
Now, at the Auth::login($laravelUser, true) the user is logged in correctly, I did check. But as soon as the page refresh sending to the final URL the session is gone.
Any Ideas?
I was facing the exact problem in Laravel 5.5. It seems that you are missing the routesMiddleware setting in saml2_settings.php file. The description says you need a group which includes StartSession, so you may want to put 'web' there, which has it included by default, as seen in Kernel.php