NativePHP / laravel

Laravel wrapper for the NativePHP framework
https://nativephp.com
MIT License
3.12k stars 161 forks source link

Websockets package doesn't support Laravel 11 #295

Closed gwleuverink closed 2 weeks ago

gwleuverink commented 4 months ago

What were you trying to do?

Hi @simonhamp, thanks for this awesome project 🚀

There is one thing I came across while implementing event broadcasting with Laravel 11.

It seems that Laravel Websockets package NativePHP integrates with has been archived and doesn't work with Laravel 11.

I need to dispatch events from a scheduled command. As I understand it right now, this doesn't work with electron's IPC. It seems only native-php events are emitted this way (or am I perhaps missing something?)

It seems like in order to support event broadcasting the same way in Laravel 11 support for Reverb needs to be added.

What happened?

The Laravel websockets package can't be installed with Laravel 11.

How to reproduce the bug

  1. Create a new Laravel 11 project
  2. Install NativePHP (0.6.3)
  3. Try to install Laravel websockets -> composer require beyondcode/laravel-websockets

Package Versions

0.6.3

PHP Version

8.2.16

Laravel Version

11.6.0

Node Version

21.7.3

Which operating systems have you seen this occur on?

macOS

OS version

macos 14.4.1

Notes

No response

gwleuverink commented 4 months ago

I've been doing some digging and it seems Laravel events are not handled using IPC in the same way native-events are.

In my case I'm dispatching a event from the scheduler using the log broadcasting connection. This event is logged in the browser (from preload.js) and I'd like to listen to it in a Livewire component.

From preload.js I gather native events are passed through Livewire, but regular events are just logged. I believe such behaviour could be achievable by adding a extra check here to detect if it is a Laravel event, then hand it off to Livewire.

Would you consider a PR adding this?

simonhamp commented 4 months ago

@gwleuverink all PRs are welcome 😊

The section you link to is specific to log events, which are generated by the LogWatcher.

All other events generated by Electron that we explicitly handle should be transformed into a native-event for the front-end and should be handled by Livewire already.

(These are also sent to the Laravel back-end, which allows you to listen to those events wherever makes the most sense for your application)

Since Laravel Reverb is out and Laravel Websockets has been archived, we may look to support Reverb.

But you should be able to achieve what you need without a websocket server in most cases. If you're struggling with your specific implementation, try reaching out on Discord.

gwleuverink commented 4 months ago

Awesome! thanks for the detailed explanation. I've been able to achieve what I set out to do. It was actually pretty straightforward.

For other folks trying to do the same: In order to listen to events dispatched with the log driver and pass it to Livewire you can do the following:

Add ipcRenderer to the js bundle (I added it to the window for the example)

window.ipcRenderer = require('electron').ipcRenderer // somehow has issues using import

Then in your component you can do something like this

<script>
    document.addEventListener('livewire:navigated', () => {
        ipcRenderer.on('log', (event, { level, message, context }) => {

            // Listen to Laravel event (could check against regex too)
            if (message.startsWith('Broadcasting [App\\Events\\MessageReceived] on channels [nativephp]')) {

                // Either dispatch event to be handled by Livewire (following native-events convention)
                window.Livewire.dispatch('native:App\\Events\\MessageReceived')

                // Or invoke the Livewire method directly
                @wire.someMethod()
            }
        })
    })
</script>

I was thinking a case can be made to handle regular Laravel events just like native-events, so this extra wiring can be skipped. But this is so little code that it is pretty manageable as is. Thanks for the assist and info @simonhamp

gwleuverink commented 2 months ago

Hi @simonhamp, I've got a follow up question regarding workaround I posted before.

It follows the same thread as the question above, but please let me know if I should ask this somewhere else. 🙏🏻

So, as demonstrated above, I'm listening to a log event that's fired when a Laravel event is dispatched on the nativephp channel, then triggering a method on a Livewire component.

This workaround works great in development, but after building the app, no log events are dispatched on ipc.

After some digging I've found that both the LogWatcher and the electron server log route are not registered when the app env isn't development.

This is probably for good reason, but I can't help but feel I'm missing something. What's the recommended way to listen to Laravel events without using websockets? Like you said, it seems most of these type of challenges can be tackled without a websocket server.

Hope you can provide some clarity! I'd be happy to contribute this back to the docs once I've got it all figured out

simonhamp commented 3 weeks ago

What's the recommended way to listen to Laravel events without using websockets? Like you said, it seems most of these type of challenges can be tackled without a websocket server.

I agree that we could achieve quite a lot of this without websockets.

This workaround works great in development, but after building the app, no log events are dispatched on ipc.

The log watcher is explicitly only for debugging and you shouldn't really abuse it in this way.

So it would be a case of building a similar solution to the LogWatcher that can pass messages across to the frontend, but that we don't disable in production.

As in your code, it would also need a listener on the frontend using ipcRenderer.on(), so this would need to be covered in the docs.

Feels like a nice easy PR...

gwleuverink commented 3 weeks ago

Thanks Simon, I was breaking my head on this one. Thought I was missing something.

It sure sounds like a great first contribution. I'll try my hand at it this week if no one beats me to it 👍

gwleuverink commented 3 weeks ago

@simonhamp I've pushed 2 PR's. Please let me know if I need to make any changes!

NativePHP/laravel#367 NativePHP/electron-plugin#37