What's NativePHP?
Did you know you can actually build desktop apps with PHP?
Yeah, there's this thing called NativePHP... 😏
Recently (well, last month actually), it got a major version update!
https://nativephp.com/blog/nativephp-for-desktop-v2-released
I'd been curious about it for a while but never actually tried implementing anything with it. So I thought, "Why not give it a shot?" and decided to build something that feels like a native app - a file explorer!
https://github.com/engineer-yone3/nativephp-de-explorer
Here's a quick walkthrough from setup to implementation for future reference.
Let's Build Something!
Installation
Before diving into NativePHP, there's one thing you need to do first: set up a Laravel environment!
composer create-project laravel/laravel
After creating your Laravel project with the usual command, install NativePHP:
composer require nativephp/desktop
Once NativePHP is installed, you need to apply it to your project.
It follows the same installation flow as other Laravel packages (like Jetstream or Livewire).
php artisan native:install
That's basically it! If you want to customize the Electron-related code that NativePHP uses under the hood, you can publish it:
php artisan native:install --publish
This will expose the code to your project for customization.
Time to Code
Since it's built on Laravel, you can implement everything using the familiar MVC pattern.
Click a button → Controller kicks in → Uses Model → Maybe implement a Service layer → Display with Blade. The usual flow!
Here's what's specific to NativePHP: when you installed it earlier, a file called app/Providers/NativeAppServiceProvider.php should have been created.
This is where you configure things like application startup settings and application menus.
class NativeAppServiceProvider implements ProvidesPhpIni
{
public function boot(): void
{
// Language menu (English is always the default on app startup)
// Menu items emit MenuItemClicked events that are handled by JavaScript
$languageMenu = Menu::make(
Menu::radio('English', true)->id('change_language_en'),
Menu::radio('日本語')->id('change_language_ja')
)->label('Language');
if (PHP_OS_FAMILY === 'Darwin') {
// For MacOS
Menu::create(
Menu::app(), // MacOS application menu (About xx)
$languageMenu
);
} else {
Menu::create(
$languageMenu
);
}
// Window settings on startup (window size, etc.)
Window::open()
->width(1920)
->height(1200)
->showDevTools(false)
->title('File Explorer')
->route('explorer.index');
}
public function phpIni(): array
{
// If you want to override php.ini settings during app runtime,
// you can configure them here
return [
];
}
}
Running and Debugging
Run php artisan native:run and your application will launch!
[windows]
[macos]
Wrapping Up
Here's a quick summary:
- NativePHP is built on Laravel. Just add the library to your Laravel setup and you're good to go
- The native part runs on Electron. You can override the default behavior if needed
- You can build for different OS and architectures
It didn't feel like learning a completely new framework - more like an extension of Laravel. That made it really easy to get started.
For this project, I kept things simple with a standard MVC approach, but since you can use Vite and other tools, I'd love to try mixing in SPA or Livewire components next time!


Top comments (2)
I have mixed feelings on NativePHP. While it is an easy solution for PHP developers. Adding PHP is an extra abstraction layer over Electron. Which is already an abstraction layer to run node on the desktop.
Desktop apps should be fast to start, but by using a script language there is always that compilation on start penalty. With compiled languages this penalty is avoided.
Thank you for the thoughtful feedback!
You’re absolutely right — while NativePHP is convenient as a scripting solution, its performance limitations become apparent (even though JIT has been getting faster over the years).
As you pointed out, there are cases where using Electron directly may be more appropriate, so NativePHP won’t solve everything. Since the version-2 line was only recently released, I’m hopeful for its future improvements.
If JIT’s performance improves and the NativePHP architecture evolves in a favorable direction, it might become a viable option going forward.