Black Friday: 40% off Bifrost Hela & Thor plans • Code: BLACKFRIDAY40
Ends in:
d
h
m
s

Events


#Overview

Many native mobile operations take time to complete and await user interaction. PHP isn't really set up to handle this sort of asynchronous behaviour; it is built to do its work, send a response and move on as quickly as possible.

NativePHP for Mobile smooths over this disparity between the different paradigms using a simple event system that handles completion of asynchronous methods using a webhook-/websocket-style approach to notify your Laravel app.

#Understanding Async vs Sync

Not all actions are async. Some methods run immediately, and in some cases return a result straight away.

Here are a few of the synchronous APIs:

Copied!
Haptics::vibrate();
System::flashlight();
Dialog::toast('Hello!');

Asynchronous actions trigger operations that may complete later. These return immediately, usually with a bool or void, allowing PHP's execution to finish. In many of these cases, the user interacts directly with a native component.

When the user has completed their task and the native UI is dismissed, the app will emit an event that represents the outcome.

The type (the class name) of the event and its properties all help you to choose the appropriate action to take in response to the outcome.

Copied!
// These trigger operations and fire events when complete
Camera::getPhoto(); // → PhotoTaken event
Biometrics::prompt(); // → Completed event
PushNotifications::enroll(); // → TokenGenerated event

#Basic Event Structure

All events are standard Laravel Event classes. The public properties of the events contain the pertinent data coming from the native app side.

#Custom Events

Almost every function that emits events can be customized to emit events that you define. This is a great way to ensure only the relevant listeners are executed when these events are fired.

Events are simple PHP classes that receive some parameters. You can extend existing events for convenience.

Let's see a complete example...

#Define your custom event class

Copied!
namespace App\Events;
 
use Native\Mobile\Events\Alert\ButtonPressed;
 
class MyButtonPressedEvent extends ButtonPressed
{}

#Pass this class to an async function

Copied!
use App\Events\MyButtonPressedEvent;
 
Dialog::alert('Warning!', 'You are about to delete everything! Are you sure?', [
'Cancel',
'Do it!'
])
->event(MyButtonPressedEvent::class)

#Handle the event

Here's an example handling a custom event class inside a Livewire component.

Copied!
use App\Events\MyButtonPressed;
use Native\Mobile\Attributes\OnNative;
 
#[OnNative(MyButtonPressed::class)]
public function buttonPressed()
{
// Do stuff
}

#Event Handling

All asynchronous methods follow the same pattern:

  1. Call the method to trigger the operation.
  2. Listen for the appropriate events to handle the result.
  3. Update your UI based on the outcome.

All events get sent directly to JavaScript in the web view and to your PHP application via a special route. This allows you to listen for these events in the context that best suits your application.

#On the frontend

Events are 'broadcast' to the frontend of your application via the web view through a custom Native helper. You can easily listen for these events through JavaScript in a few ways:

  • The globally available Native.on() helper
  • Directly importing the on function
  • The #[OnNative()] PHP attribute Livewire extension

The Native.on() helper

Register the event listener directly in JavaScript:

Copied!
@use(Native\Mobile\Events\Alert\ButtonPressed)
 
<script>
Native.on(@js(ButtonPressed::class), (index, label) => {
alert(`You pressed button ${index}: ${label}`)
})
</script>

This approach is useful if you're not using any particular frontend JavaScript framework.

The on import

If you're using a SPA framework like Vue or React, it's more convenient to import the on function directly to register your event listeners. Here's an example using the amazing Vue:

Copied!
import { on, Events } from '#nativephp';
import { onMounted } from 'vue';
 
const handleButtonPressed = (payload: any) => {};
 
onMounted(() => {
on(Events.Alert.ButtonPressed, handleButtonPressed);
});

Note how we're also using the Events object above to simplify our use of built-in event names. For custom event classes, you will need to reference these by their full name:

Copied!
on('App\\Events\\MyButtonPressedEvent', handleButtonPressed);

In SPA land, don't forget to de-register your event handlers using the off function too:

Copied!
import { off, Events } from '#nativephp';
import { onUnmounted } from 'vue';
 
onUnmounted(() => {
off(Events.Alert.ButtonPressed, handleButtonPressed);
});

The #[OnNative()] attribute

Livewire makes listening to 'broadcast' events simple. Just add the #[OnNative()] attribute attached to the Livewire component method you want to use as its handler:

Copied!
use Native\Mobile\Attributes\OnNative;
use Native\Mobile\Events\Camera\PhotoTaken;
 
#[OnNative(PhotoTaken::class)]
public function handlePhoto(string $path)
{
// Handle captured photo
}

#On the backend

You can also listen for these events on the PHP side as they are simultaneously passed to your Laravel application.

Simply add a listener as you normally would:

Copied!
use App\Services\APIService;
use Native\Mobile\Events\Camera\PhotoTaken;
 
class UpdateAvatar
{
public function __construct(private APIService $api) {}
 
public function handle(PhotoTaken $event): void
{
$imageData = base64_encode(
file_get_contents($event->path)
);
 
$this->api->updateAvatar($imageData);
}
}