Native PHP Apps (2/∞)

Exploring NativePHP.

Introduction

In the last post, I mentioned something about being able to trigger desktop notifications right from your NativePHP app. Today, I wish to test it out and see if it'll be easy to do.

Getting the application set up took quite a while, and I had to dig through the Github issues of the repository in order to find a way to get the app running. Clearly, there is still a lot of work to be done in order to make the set up as smooth and seamless for as many platforms as possible.

For that reason, I will not show how to set up the app at this time. But if you have any issues, do well to consult the repository.

TLDR: I just need the code

If you're not interested in reading the full article here, you can find the necessary code in this commit.

Running the app

To get Electron to open up, we just need to build and then run.

So I did php artisan native:build win to build.

And then php artisan native:serve to start the server.

What this did was to open up a native Electron window.

By default, it opened up my DevTools as well. We'll just go ahead and close that.

Modifying UI

Now we need to add a button that we can click to show the notifications. Since we're working in Laravel, we already have a welcome.blade.php view by default. And the 4 items that appear are actually all just buttons, so we'll just duplicate them.

<div class="mt-16">
    <div class="grid grid-cols-1 md:grid-cols-2 gap-6 lg:gap-8">
        <button id="runButton" class="scale-100 p-6 bg-white dark:bg-gray-800/50 dark:bg-gradient-to-bl from-gray-700/50 via-transparent dark:ring-1 dark:ring-inset dark:ring-white/5 rounded-lg shadow-2xl shadow-gray-500/20 dark:shadow-none flex motion-safe:hover:scale-[1.01] transition-all duration-250 focus:outline focus:outline-2 focus:outline-red-500">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white">Show notification</h2>
        </button>

        ...

</div>

And then when we run it, we get:

Certainly not the best UI, but just a proof of concept.

Now we want that button to do something when clicked, so we already gave it an ID of runButton. We'll create a script on this same welcome page that sends a POST request to the appropriate controller which will then invoke the notification.

So before our closing body tag, we can create a script like so:

<script>
    document.getElementById('runButton').addEventListener('click', function() {
        // Send an AJAX request to the route
        fetch("{{ route('run.method') }}", {
            method: 'POST',
            headers: {
                'X-CSRF-TOKEN': '{{ csrf_token() }}',
                'Content-Type': 'application/json',
            },
        })
        .then(data => {
            // Handle the response or update the UI as needed
        })
        .catch(error => {
            console.error('An error occurred:', error);
        });
    });
</script>

The main takeaway from this script is the fetch() method which sends a POST request to the server. We have not yet defined the target endpoint, so let's do that.

Endpoint and Controller

Before we add the endpoint to the default routes in web.php, let's go ahead and create the controller.

With Artisan, it's pretty easy to generate. Since we don't need multiple methods, the simplest thing here is to use the shortcut flag to generate an invokable controller:

php artisan make:controller -i NotificationButtonController

Then in the controller, we can just modify the __invoke class as follows:

public function __invoke()
{
    Notification::title('Hello from NativePHP')
        ->message('This is a detail message coming from your Laravel app.')
        ->show();
}

This example was actually lifted straight out of the documentation.

Now we can link this controller in our web.php routes:

<?php

use App\Http\Controllers\NotificationButtonController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::post('/run-method', NotificationButtonController::class)->name('run.method');

Testing the code

Now we can just refresh the Electron window (using the relevant keyboard shortcut) and then click the button. It will gracefully display a native notification!

Conclusion

I hope you can see how easy it was!