Laravel pusher event not getting triggered - javascript

Here is my .env code->
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=xxxxx
PUSHER_APP_KEY=xxxxx
PUSHER_APP_SECRET=xxxxx
PUSHER_APP_CLUSTER=xxxxx
Here is my config code ->
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
'encrypted' => true,
],
],
Here is my event code ->
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class orderEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $text;
public function __construct($text)
{
$this->text = $text;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('fish20');
}
}
and finally here is my route for testing from which i trigger the event but nothing actually happens :( . ->
Route::get('/get', function () {
$text = 'New order received.';
event(new orderEvent($text));
});
I cannot see any event triggered on debug console
of my pusher channel.

You should use broadcast(new orderEvent($text)); instead of event(new orderEvent($text)); in your route.

I got the solution. for some reason laravel uses Queue in events and my queue connection was database so like this -> QUEUE_CONNECTION=database and i removed that and made it sync so that it gets trigger and dosent queue it for later like this -> QUEUE_CONNECTION=sync
Also there is another way on your event file instead of ShouldBroadcast use this -> ShouldBroadcastNow

You need to share your client side code too.
If you forgot to implement the client code, you can read the official document about Broadcasting. I also found this tutorial which uses an older version of Laravel, but the concept hasn't changed much.

Related

Laravel Echo does not listen for public channel events?

I am using Laravel Websockets package.Everything looks great on server side but Laravel Echo is not listening to events..
MySocketEvent.php:
<?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;
class MySocketEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $data;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($data)
{
//
$this->data=$data;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('DemoChannel.1');
}
public function broadcastAs()
{
return 'testing';
}
}
Web.php
Route::get('tests',function(){
$arr=['some'=>'some'];
broadcast(new \App\Events\MySocketEvent($arr));
return view('hi');
});
Bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
//key: process.env.MIX_PUSHER_APP_KEY,
key: 'my-key',
wsHost: window.location.hostname,
wsPort: 6001,
wssPort: 6001,
disableStats: true,
cluster: 'ap2',
//cluster: process.env.MIX_PUSHER_APP_CLUSTER,
//encrypted: true
});
//subscribe-for-the-test-demo-channel-and-listen
window.Echo.channel('DemoChannel.1')
.listen('.testing', (e) => {
console.log("Received Data: ");
console.log(e);
});
I see the data sent from server by using php artisan WebSockets:serve but Laravel Echo does not listen. Please help. I'm 100% sure problem is with Laravel Echo.
The "dot" before "testing"
Broadcasting As "testing"
Listening For ".testing"
Replace this
window.Echo.channel('DemoChannel.1')
.listen('.testing', (e) => {
console.log("Received Data: ");
console.log(e);
});
To this
window.Echo.channel('DemoChannel.1')
.listen('testing', (e) => {
console.log("Received Data: ");
console.log(e);
});
Update:
Add this line to your event file
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
Replace this
class MySocketEvent implements ShouldBroadcast
To this
class MySocketEvent implements ShouldBroadcastNow
I was able to get Echo working by downgrading pusher to 4.4.0
npm install pusher-js#4.4.0

NodeJS events triggering multiple times in electron-react app

I have a package (Let's say PACKAGE_A) written to do some tasks. Then it is required by PACKAGE_B. PACKAGE_A is a node script for some automation work. It has this Notifier module to create and export an EventEmitter. (The Whole project is a Monorepo)
const EventEmitter = require('events');
let myNotifier = new EventEmitter();
module.exports = myNotifier;
So in some functions in PACKAGE_A it emits event by requiring myNotifier, and also in the index.js of PACKAGE_A, I export functions (API exposed to the other packages) and the myNotifier by requiring it again.
const myNotifier = require('./myNotifier);
const func1 = () => {
// some function
return something;
}
module.exports = {func1, myNotifier}
Then I import the PACKAGE_A in PACKAGE_B and use the API functions exposed with the notifier. PACKAGE_B is an electron app with a React UI.
Below is how the program works.
I have a console output window in the electron app (React UI, UI_A). <= (keep this in mind)
When I click a button in UI_A it fires a redux action (button_action). Inside the action, a notification is sent to an event which is listened in the electron code using ipcRenderer.
ipcRenderer.send('button-clicked', data); // <= this is not the full code of the action. It's bellow.
Then in the electron code (index.js), I require another file (UI_A_COM.js which houses the code related to UI_A in electron side). The reason is code separation. Here's part of the code in index.js related to the electron.
const ui_a_com = require('./electron/UI_A_COM');
const createWindow = () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
resizable: false,
});
mainWindow.loadURL('http://localhost:3000');
const mainMenu = Menu.buildFromTemplate(menuTemplate);
ui_a_com (mainWindow);
};
Alright. Then in UI_A_COM.js, I listen to that triggered event button-clicked.
ipcMain.on('button-clicked', someFunction);
which runs the code from PACKAGE_A and return a result. So now when PACKAGE_A runs, it emits some events using myNotifier. I listen to them in the same file (UI_A_COM.js), and when those events are captured, I again send some events to React UI, which is subscribed when button_action fired.
myNotifier.on('pac_a_event_a', msg => {
mainWindow.webContents.send('ui_event_a', msg); // code in `UI_A_COM.js`
});
Here's the full code for the action. (Did not provide earlier because you'll get confused)
export const buttonAction = runs => {
return dispatch => {
ipcRenderer.send('button-clicked', data);
ipcRenderer.on('ui_event_a', (event, msg) => {
dispatch({ type: SOME_TYPE, payload: { type: msg } });
});
};
};
This will show the msg in the UI_A console.
So this is the task I'm doing. The problem is when I click the button; it works perfectly for the first time. But when I click the button on the second time, it received two messages. Then when I click the button again, three messages and it keeps growing. (but the functions in the PACKAGE_A only executes one time per button press).
Let's say the message from PACKAGE_A emitted is 'Hello there' per execution.
When I press the button 1st time a perfect result => Hello there, When I click the button again => Hello there Hello there, When I click it again => Hello there Hello there Hello there.
It's kept so on. I think my implementation of EventEmitter has some flows. So why it's happening like this? Is it EventEmitter or something else? What am I doing wrong here?
By default the electron-react boilerplate doesnt define the ipcRenderer.removeAllListeners method. So you have to first go to the main/preloads.ts file and add them :
removeListener(channel: string, func: (...args: unknown[]) => void) {
ipcRenderer.removeListener(channel, (_event, ...args) => func(...args));
},
removeAllListeners(channel: string) {
ipcRenderer.removeAllListeners(channel);
},
Then go to the renderer/preload.t.s declaration file and add the declarations too:
removeListener(
channel: string,
func: (...args: unknown[]) => void
): void;
removeAllListeners(channel: string): void;
After that make sure to clean all listeners in the cleanup function of your useEffects each time you listen to an event fired. This will prevent multiple firing.
useEffect(() => {
window.electron.ipcRenderer.on('myChannel', (event, arg) => {
// do stuffs
});
return () => {
window.electron.ipcRenderer.removeAllListeners('myChannel');
};
});
I think you should return a function that call ipcRenderer.removeAllListeners() in your component's useEffect().
Because every time you click your custom button, the ipcRenderer.on(channel, listener) is called, so you set a listener to that channel agin and agin...
Example:
useEffect(() => {
electron.ipcRenderer.on('myChannel', (event, arg) => {
dispatch({ type: arg });
});
return () => {
electron.ipcRenderer.removeAllListeners('myChannel');
};
});

Laravel Event Broadcast not being picked up laravel-echo-server

I'm attempting to use laravel-echo-server (socket.io) I'm getting a roadblock where the client-side doesn't appear to be getting any broadcasted events.
Everything seems to be connected fine and socket.io server is reporting that it's connecting and authorising the user however when I broadcast a message nothing seems to happen. The event is appearing on Laravel Horizon but otherwise, nothing happens. Here is my code:
server.js to run the laravel-echo-server:
require('dotenv').config();
const env = process.env;
require('laravel-echo-server').run({
authHost: env.APP_URL,
devMode: env.APP_DEBUG,
database: "redis",
databaseConfig: {
redis: {
host: env.REDIS_HOST_PUBLIC,
port: env.REDIS_PORT,
}
}
});
My channel in channel.php
Broadcast::channel('message.pushed', function () {
return true;
});
My event:
<?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\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MessagePushed implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{
$this->message = "My New Message";
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('message.pushed');
}
}
My event listener within app.js
import Echo from 'laravel-echo';
window.io = require('socket.io-client');
if (typeof io !== 'undefined') {
var token = $('meta[name="_token"]').attr('content')
window.Echo = new Echo({
auth : {
headers: {
Authorization: `Bearer ${token}`,
},
},
broadcaster: 'socket.io',
host : window.location.hostname + ':6001',
});
}
function listenForBroadcast() {
Echo.private('message.pushed')
.listen('MessagePushed', (e) => {
console.log(e)
console.log("Listened")
});
}
listenForBroadcast();
Lastly the route sending the message:
Route::get('/event-test', function () {
broadcast(new App\Events\MessagePushed());
});
I am not quite sure where i have gone wrong or why nothing is being picked up by the client.
While looking in laravel-echo-server the command line is echoing:
Channel: laravel_database_private-message.pushed
Event: App\Events\MessagePushed
In you browser you need to listen on Channel as shown by redis and also listen to the event as shown by redis, so changing your listenForBroadcast() method may help.
In the code, Channel name changed from message.pushed to laravel_database_private-message.pushed and Event name changed from MessagePushed to .App\Events\MessagePushed ( Do not miss dot prefix to App )
function listenForBroadcast() {
Echo.private('laravel_database_private-message.pushed')
.listen('.App\\Events\\MessagePushed', (e) => {
console.log(e)
console.log("Listened")
});
}
I tried this solution based on the solution given in the following link and it worked for me
laravel Echo does not listen to channel and events

how to pass object from view to controller

I have an object $trial that fills up while in the view. I would like to pass it to route as POST to call a function using it's data. This is to create an event for fullcalendar. I'm pretty sure that I've been sitting on this so long, that I'm way overthinking it.
Wanted to do this with eventRender callback but couldn't figure out how to pass the data into it, tried simple $.post just to get method not allowed or unknown status in the console.
I have some dummy data at the moment.
The goal here is to create event through marked time range.
Controller function to add new record to database if I manage to pass data
public function addEvent(Request $request)
{
//dd($request);
$event = new Event;
$event->title = $request['title'];
$event->start_date = $request['start_date'];
$event->end_date = $request['end_date'];
$event->save();
\Session::flash('success','Event added successfully.');
return redirect('/events');
}
web.php (routing)
Route::get('/events', 'EventController#index');
Route::post('/events', 'EventController#addEvent');
and then there is the index function on which I work the most currently to modify the table (make it editable, etc).
public $trial = [];
//
public function index()
{
$events = [];
$data = Event::all();
if($data->count()) {
foreach ($data as $key => $value) {
$events[] = Calendar::event(
$value->title,
true,
new \DateTime($value->start_date),
new \DateTime($value->end_date.' +1 day'),
null,
// Add color and link on event
[
'color' => '#f05050',
'url' => '/events',
]
);
}
}
$calendar = Calendar::addEvents($events) //add an array with addEvents
//->addEvent($eloquentEvent, [ //set custom color fo this event
//'color' => '#800',
//])
->setOptions([ //set fullcalendar options
'firstDay' => 1,
'selectable' => true,
'unselectAuto' => false,
'selectOverlap' => false,
'editable' => true,
'businessHours' => [
'dow' => [ 1, 2, 3, 4, 5 ],
'start'=> '08:00',
'end' => '19:00',
]
])->setCallbacks([ //set fullcalendar callback options (will not be JSON encoded)
'eventClick' => 'function(event) {
console.log("You clicked on an event with a title of: " + event.title);
}',
'select' => 'function(start, end) {
console.log("Selection start: " + start.format() + " selection end: " + end.format());
$trial = {
title: "rent",
start_date: start.format(),
end_date: end.format()
};
console.log($trial);
}',
]);
any suggestions would be welcome.
EDIT: generally, pretty much the only way i know how to pass data to be used in functions in controller is submitting it through form
I don't use Angular specifically, but it's got many similarities with Vue. I use a platform-agnostic package called Axios which allows you to send requests to your server.
To backtrack a second, a form is basically a general way to send a post request. The url is specified in the form, and the values are the input fields.
With any package, you would do something similar:
specify the url
specify the request type (post, get, etc)
pass parameters (but not required)
With Axios, it would look something like:
axios.post('/mySite.com/something', { datum1: 'value', datum2: true })
.then(response => () {
this.someFunction(response.data);
});
This has some ES6 magic in it (arrow functions), but this is very similar to many requests. Like I said, the second parameter is optional, or you can even pass a data object.
Don't forget to also include the csrf token. This is easiest if you just add in as a meta tag in your page head (see the Laravel Docs), but you can also pass it in directly as a _csrf parameter.

Pusher receives no events

i am using laravel with pusher to send an event message to pusher. the code is in my controller which is a post controller, triggered when an input form is submitted. below is my code. what am i doing wrong? there is no event received.
this is an ajax call route based controller.
$pusher = new Pusher( env('PUSHER_KEY'), env('PUSHER_SECRET'), env('PUSHER_APP_ID'), array( 'encrypted' => true ) );
$pusher->trigger( 'test_channel', 'my_event', 'hello world' );
I am also assuming you have set up your Pusher account correctly and that your environment variables are correct.
If so, you may need to ensure you are using the correct Cluster (the default is fine for the US, but outside the East coast of the US for example, the cluster must be explicitly defined).
Update:
Controller code:
<?php
namespace App\Http\Controllers;
use Vinkla\Pusher\Facades\Pusher;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class TestPusherController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function test(){
$arr = array('test' => 'hello world 2') ;
$pusher = new Pusher( env('PUSHER_KEY'), env('PUSHER_SECRET'), env('PUSHER_APP_ID'), array( 'encrypted' => true, 'cluster' => 'ap1' ) );
$pusher::trigger( 'test_channel', 'my_event', $arr);
return $arr;
}
public function shortenedTest(){
$message = 'Hello world';
Pusher::trigger('my-channel', 'my-event', ['message' => $message]);
}
}
In web routes:
Route::get('testPusherController', 'TestPusherController#test');
Route::get('shortenedTestPusherController', 'TestPusherController#shortenedTest');
I have got this working on a fresh install of vinkla/pusher following the setup steps in https://github.com/vinkla/laravel-pusher, on Laravel 5.3, using the built in PHP server and Connecting to the EU server (I do not have any Pusher apps using ap1 at this time).
You will notice a small number of changes to the coding in the controller to get the correct format. You must 'use' the Pusher facade above the controller.
For completeness, I have added a neater way of working with this where you can set the Pusher credentials in the Config/pusher.php file without the need to setup the connection for each use. This can be seen in the shortenedTest() method on the controller.
<?php
return [
'connections' => [
'main' => [
'auth_key' => env('PUSHER_KEY'),
'secret' => env('PUSHER_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_CLUSTER')
],
'host' => null,
'port' => null,
'timeout' => null,
],
'alternative' => [
'auth_key' => 'your-auth-key',
'secret' => 'your-secret',
'app_id' => 'your-app-id',
'options' => [],
'host' => null,
'port' => null,
'timeout' => null,
],
],
];

Categories