laravel-websockets
                                
                                 laravel-websockets copied to clipboard
                                
                                    laravel-websockets copied to clipboard
                            
                            
                            
                        Bi-directional broadcasting with Laravel echo
I have a server configured for multi tenancy, I can broadcast events with private channels from my applications to front end clients using the Laravel echo client to listen for events but I actually wish to emit events from the front end too, to trigger events on back end.
Is this possible with this package or is this strictly server to client broadcasting only?
This is definitely possible. Have a look at https://docs.beyondco.de/laravel-websockets/1.0/basic-usage/pusher.html#usage-with-laravel-echo and the Laravel docs on Laravel Echo. Good luck!
Thanks for your response Alex, however I still feel there is something missing. For example how do I make My Laravel application listen for the events from the client and handle them accordingly.
Apologies if I’m missing something obvious here, but I can’t find any useful documentation for this. Everything seems to be related to broadcasting server to client or client to client but not client to server
I'm using laravel echo to websocket the search, I need to inform the server of what the user is typing (and other cases, tables, that I need to send pagination info). So I really require this to procced.
@RafaelCorreaQuantik - did you find a solution to this ? I've heard others are using Redis to achieve this, but it's websockets right. Should be definitely allow for bi-directional communication. For now I've resulted to just using ajax for posting back to the server
@minimatrix - I found out about window.Echo.connector.socket.emit, couldn't test it right, and also. I don't know how to handle the server side of this request.
@RafaelCorreaQuantik This package is currently only showing to way to be a pusher replacement. It does not show any bi-directional communication example, though from the codebase it looks like possible.
I too was interested with the their websocket in php, done right statement, but too bad it isn't have much information about it yet. If you have any clue please share it with us. Thank you.
@justinmoh, maybe this is a pusher limitation indeed. Changing from pusher to socket io would be really hard at this point for the package. But may the only option, since socket.io natively supports bi directional communication.
I've been investigating this window.Echo.connector.socket.emit implementation and found this issue by luck. Here are my final notes:
- Socket.io's emit function can update Redis but the problem is the server implementations between client and backend. This is what I see here too. Echo and Laravel WebSockets are failing on the exact same subject.
- Laravel Echo Server does not listen client events and they are not planning to do in future. (check this and many more issues about this subject are closed state now)
- If Echo or Laravel Websockets implements this approach successfully, you may use Redis Pub/Sub listen and trigger events on server side.
Unfortunately there's a lot of reasons this is tricky to handle.
- ReactPHP is an async event loop framework, meaning that any blocking IO will cause the websocket server to stall. This means any of the stock SQL or Redis connections/libraries used in Laravel can't be used from code that runs on the websocket server.
- To get around this, you can use https://github.com/clue/reactphp-redis which is an async Redis client, which would let you communicate with Redis efficiently from within the websocket server.
- But the problem is that the Laravel Redis queue driver doesn't support react-redisconnections for pushing jobs onto the queue. This means you'd have to implement your own driver (or wait for someone else to write one - actually this is something that interests me, and I know how to do this, so I might write this as a library at some point in the future when I find some extra time)
- You could go the SQL route with https://github.com/friends-of-reactphp/mysql but again, Eloquent doesn't support these kinds of connections, so you'd have to write raw SQL (not a deal breaker, just a bummer). Then you'd need to set up polling for changes in the DB if you want to actually do some other kind of IO.
- etc.
All that to say, just use ajax. It's way easier, and it's a direct channel to your backend anyways. Ajax is very fast if you stick to small JSON messages, even better if you use HTTP/2 so it'll re-use the same TCP connection (I think).
I cannot give you code right now but I can give you the idea. Try to use a custom implementation of WebSocketHandler(find custom handler option in docs) and copy the complete code of WebsockerHandler.php of this package. In the onMessage() method you will be able to handle the incoming messages.
Don't forget to enable client messages option in config file.
Hope that helps.
Just a random thought, but this could be possible if the package was able to send jobs to the queue. The real work would be done in a worker with full access to Laravel, the package would only receive incoming WebSockets messages (which it already does for pings & whispers).
Queue connections would have to be async, though. I know there are ReactPHP clients for Redis and it's apparently possible to have the AWS SDKs in the event loop, which would allow supporting SQS.
Also, Laravel Echo would have to be extended to support client->server messaging (besides whispers).
Something like this:

I know the idea is to be a replacement for Pusher, but this wouldn't break the protocol, it would extend it. Everything you can do with Pusher would still be possible, plus you would gain the ability to receive incoming messages.
Additionally, we could make use of the channel classes and add more methods to it, like:
<?php
namespace App\Broadcasting;
use App\Room;
use App\User;
class ChatChannel
{
    public function join(User $user, Room $room)
    {
        if ($room->wasBanned($user)) {
            return false;
        }
        return $user;
    }
    public function createMessage(User $user, $data)
    {
        $room = $user->joinedChats()->findOrFail($data['room_id']);
        $message = new Message(['content' => $data['content'], 'user_id' => $user->id]);
        $room->messages()->save($message);
        
        broadcast(new ChatMessage($message));
    }
}
In Echo, something like this would do the trick:
const channel = Echo.join(`chats.${roomId}`)
    .here((users) => {
        //
    })
    .joining((user) => {
        console.log(user.name);
    })
    .leaving((user) => {
        console.log(user.name);
    });
// when user sends a message:
channel.perform('createMessage', { room_id: roomId, content: 'Hello world!' });
The ChatChannel::createMessage method would be called in the worker, in this example.
The only "drawback" about the current broadcasting component in Laravel is that it doesn't make use of the bi-directional, full-duplex nature of WebSockets due to the Pusher protocol limitation.
I'm not sure if adding this would be that beneficial over AJAX, as it won't be real-time (as the message would have to go through a view hops to be handled and the side-effects to be broadcasted again). However, folks in the Rails world have done something similar with AnyCable but using gRPC instead of a queue.
Thoughts? Should I open a new issue for further discussion?
Yeah your thoughts basically align with what I wrote above. We just need someone to write a queue driver that uses https://github.com/clue/reactphp-redis. The rest is basically a given once that exists. I've wanted to spend time doing that, but I don't particularly need this feature myself so I haven't yet.
I might find some time over the festive period to write this queue driver, it’s something that I feel will add value to this project
On Sat, 21 Dec 2019 at 21:00, Francis Lavoie [email protected] wrote:
Yeah your thoughts basically align with what I wrote above. We just need someone to write a queue driver that uses https://github.com/clue/reactphp-redis. The rest is basically a given once that exists. I've wanted to spend time doing that, but I don't particularly need this feature myself so I haven't yet.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/beyondcode/laravel-websockets/issues/190?email_source=notifications&email_token=AFUKRJRNRXEJQSHGTHBMKT3QZZ7VDA5CNFSM4HV65GTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHPDQ7Q#issuecomment-568211582, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFUKRJTSPJ33G2LZ65RNQETQZZ7VDANCNFSM4HV65GTA .
If you do, feel free to @ me for a code review 😄
Did anyone has implemented a clear solution for this issue yet?
We need to bring bi directional broadcasting with Laravel echo, we can currently do it with posting data with axios back to server and then doing a broadcasting on the backend but this doesn't work in realtime there is a small amount of delay in working of them, when using Socket.io with NodeJS backend everything works in real time and without delay, this might be also because of NodeJS it self, PHP takes time for excuetion than NodeJS. But if we have broadcasting or emmitting from the client it self then we can do it more productive way and the simplicity of the design would be maintained.
So as a general announcement, now beta, 2.x version does come with multi-node support for horizontal scaling thanks to @francislavoie <3 The underlying code uses ReactPHP Redis' implementation for non-blocking I/O, but I am not really sure
This deems to be a good idea for the Laravel package itself, as well as the laravel/echo repo, because it lacks the ability to emit custom events directly from the pusher provider in Echo client: https://github.com/laravel/ideas/issues/2350
The only workaround is to use a custom endpoint that will do that for you, like taking the body and handing it to the backend or via a queue message manager. @veermetri05 You can use client-to-client whispering instead of processing the backend over and over again, unless you need additional backend code to be ran.
Like I said earlier:
We just need someone to write a queue driver that uses clue/reactphp-redis.
If that's set up, then L-W can easily broadcast jobs to the queue using that driver for bidirectional messages to work.
@francislavoie @tonysm I have written the queue driver a while back, guess I'll have to push it and write tests for it.
@francislavoie @tonysm I have pushed the changes to https://github.com/beyondcode/laravel-websockets/pull/552, take a look whenever you can.
I was wondering if anyone could clarify if this functionality is now possible? It seems like the prerequisites are done but I'm not sure if this feature was ever implemented?
I recently was able to achieve bi directional communication with Laravel. Laravel Broadcasting for server to client communication while using websockets api for client to server communication. My SO answer: https://stackoverflow.com/a/74310959/13933721
I'm not sure your code works @kpebron ?! can you explain how to listen redis for emitted messages from client and save them to database?  (laravel-echo-server + socket.io-client)

No progress?
No progress?
No progress. vervsion 2.x is outdated and no longer update. I think this because of swoole and laravel octane. Swoole has its own websocket server and does not have i/o and async issues, i think community must work on enchance swoole support in laravel octane to bring all swoole features to work, because now swoole in octane in very starting point.
I'm not sure your code works @kpebron ?! can you explain how to listen redis for emitted messages from client and save them to database? (laravel-echo-server + socket.io-client)
Not socket.io but websockets. socket.io has different setup (I think). I did this last year and kind of forgot how to do this again. besides this was more of a hack-ish kind of solution. It would be great if laravel-websockets could implement this naturally without complicated setup.
I'm stuck on the same issue
I understand that Pusher - as the name suggests - pushes from the server to the client. Still, my use case is different because I'm implementing an online auction system and the bids need to happen through a bi-directional connection since I can't fire an XHR request every single time someone makes a bid because it would be a complete kill, and when I say a "complete kill" then I mean it because I've created a script that simulates bidding operations and made it run and create thousands of virtual bids per second. I felt like I've DDoS-ed myself, so using XHR isn't an option at all in this case ...
And if I understand correctly, then Laravel doesn't seem to be able to listen to any client-side events, and at this point, I've started to question myself whether Laravel was the correct choice for this kind of project in the first place, but I don't know ...
@Eyad-Mohammed-Osama you just need to be using Laravel Octane, then the XHR requests to your server will have nearly zero overhead compared to a bidirectional connection. All of the overhead is from framework bootstrap, but that's completely avoided with Octane because it keeps a worker running to accept requests without redoing the bootstrap.
As I wrote above in this issue, I don't think people understand how much more complexity is added when involving bidirectional websockets. It's also risky to run your own code in reaction to incoming messages, unless you're careful to only use libraries/clients that are properly async. Any blocking IO would cause your WS server to stall until the IO is done, ruining performance.
@francislavoie Thanks for the suggestion. I'll definitely take my time to look more into Laravel Octane, it seems promising for my use case.
I understand your point about bidirectional web sockets and the complexity behind them. While I was working on the auction feature, I've already tried something like this:
I thought that maybe I could make a Node.JS server that proxies the incoming requests to the Laravel backend through some IPC mechanism, or maybe by passing the data through a Laravel console command, but this was painful to do for several reasons:
- The authentication flow for private and presence channels was very complicated because the user must send their bearer token to the socket server, and the socket server must proxy this to an authentication endpoint or a command in the Laravel project which checks whether a user is eligible to subscribe to the channel or not and send the result back to the Socket.IO server, and this was a whole another story because the async Socket.IO server will have to wait for the response to come back from the sync Laravel server
- I had many security and performance concerns
So I didn't do it because I couldn't take any chances. I may do this in my spare time as a side project, but not on a production project.
You may use openswoole for bidirectional socket connection. But if you want to use Laravel you should use message broker such as rabbit or redis for connection between laravel and nodejs (or everything handles socket) In this case laravel echo uses redis as message broker but. It is fast but not safe!