Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Bin Laravel Package

nativephp/php-bin

Precompiled, portable PHP binaries that let NativePHP apps run PHP without a system install. Ships static builds for multiple platforms, simplifying packaging and distribution of desktop PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

nativephp/php-bin is not an application-level library — it is a distribution artifact that ships precompiled PHP runtimes for NativePHP desktop apps. You rarely reference it directly; it arrives as a transitive dependency when you install nativephp/electron (or the desktop runtime package) and is resolved at build time, not runtime.

Minimal path:

composer require nativephp/electron
php artisan native:install
php artisan native:serve   # dev preview uses a bundled PHP runtime
php artisan native:build   # packaging step pulls the matching php-bin artifact

Where to look first, in order:

  1. composer.lock — confirm which nativephp/php-bin version you resolved, which PHP minor it maps to, and which platform artifact was pulled.
  2. The NativePHP runtime package's config/nativephp.php (or native.php) for the php / binary / version keys.
  3. The extracted runtime location after a native:build — that is where you debug "my app works in artisan serve but not in the packaged bundle."

First real use case: shipping a Laravel app as a .dmg / .exe / AppImage to users who do not have PHP installed. php-bin is the piece that makes that promise true — it removes the "install PHP first" step from your distribution.

As of 1.2.0 the shipped runtime matrix covers PHP 8.3, 8.4, and 8.5 on linux (arm64 + x64), macOS (arm64 + x64), and Windows x64 only. That version matrix is your first decision: check it before you write code, not after.

Implementation Patterns

Write normal Laravel, then wrap it. There is no php-bin API surface. Your controllers, jobs, and Artisan commands are unchanged. The package's job is to make php artisan, queue workers, and the embedded HTTP server run inside the packaged app without a system PHP.

Pin the PHP runtime deliberately. Treat the PHP version like a lockfile entry:

{
  "require": {
    "nativephp/electron": "^1.0"
  },
  "config": {
    "platform": { "php": "8.4.0" }
  }
}

The platform pin keeps Composer resolving dependencies compatible with the shipped runtime, not your dev machine's PHP. Mismatch here is the single most common source of "works on my laptop, crashes in the installer."

Since 1.2.0 you can pin to 8.5 — but only do so if your dependency tree genuinely supports it. The safer default for an existing app is to stay on 8.3 or 8.4 and upgrade the runtime as a deliberate, tested step. Do not pin platform to 8.5 because it is newest; pin it because you verified native:build on every target.

Build per-target in CI, not cross-compiled. One matrix job per {macos, windows, linux} × {arm64, x64}. Each job installs its own php-bin artifact and produces its own installer. Do not try to produce a Linux bundle from a macOS runner — the artifact is platform-specific. Note the asymmetry in the published matrix: Windows is x64 only, so an arm64 Windows build is not something you can ship today regardless of your CI setup.

Keep the app free of system-PHP assumptions. Audit for things that break inside a bundled runtime:

  • exec('php ...') — the app has no php on $PATH; call PHP_BINARY instead.
  • ini_get() values you rely on in dev — the bundled runtime ships its own php.ini; verify extensions and limits explicitly.
  • Writable paths — storage/, bootstrap/cache/, and log directories must resolve inside the packaged app or a user-scoped appdata path, not your dev tree.

Extension policy: compile-time, not runtime. php-bin ships a fixed extension set per build. If you need pdo_pgsql, gd, imagick, or similar, confirm they are in the artifact before you write code depending on them. Enabling an extension is not php -m-and-done — it requires a runtime built with it, meaning a custom php-bin fork or an upstream build request.

Sodium is now bundled (1.2.0). If you previously worked around a missing sodium — a userland fallback via paragonie/sodium_compat, or a hand-rolled signing path — 1.2.0 removes the reason. Worth revisiting: code paths that silently degraded to pure-PHP crypto can now use the native extension, and any composer.json ext-sodium requirement you suppressed can be restored. Verify with php -m from inside a packaged build before relying on it, and remember the fallback may still be needed if you also support older pinned php-bin versions in the field.

TLS trust store ages with your pin. The CA bundle is refreshed on a rolling basis by automation (three such updates landed in this release alone). A pinned, stale php-bin means a stale root store — packaged apps making outbound HTTPS calls can start failing certificate validation long after release. Bake a periodic "bump php-bin, rebuild, smoke-test outbound HTTP" task into your maintenance cycle rather than treating the runtime as set-and-forget.

Version alignment across the stack. Keep nativephp/electron, nativephp/php-bin, and your app's composer.lock on a coherent set. Upgrading the runtime without re-resolving app dependencies is a coin flip on binary compatibility. The 1.2.0 bump also moves the underlying static build toolchain (SPC 2.8.2) — a runtime rebuild can change patch-level behaviour even when the PHP minor is unchanged.

Local dev loop. Use the native dev server during development (native:serve), but periodically run a full native:build on each target — the packaged runtime is a different PHP than your CLI, and that gap is where bugs hide.

Gotchas and Tips

It is not require-able for features. If you find yourself writing use NativePHP\PhpBin\... in application code, you've misread the package. It's a build dependency. Treat every file under it as opaque.

"Composer says success, app fails at boot." The bundled PHP's php.ini, extension set, and memory_limit differ from your dev CLI. Debug by printing PHP_BINARY, php -v, and php -m from inside the packaged app — write them to a log file next to the executable, since you have no terminal attached.

Upgrading to 1.2.0 changes the artifact contents. Unused macOS binaries were pruned in this release. The installer gets smaller, but any CI step, signing script, or path assumption that referenced a specific binary inside the extracted runtime can break. Diff the extracted tree between 1.1.x and 1.2.0 on macOS before you ship the upgrade.

Windows on arm64 is not covered. The 1.2.0 matrix publishes Windows x64 builds only. If a user reports a Surface-class arm64 device, they will run your x64 installer under emulation — plan and test for that, or scope the platform out explicitly.

macOS: signing and notarization. The bundled PHP binary is a nested executable. Hardened runtime + notarization must cover it explicitly. An unsigned or non-entitled nested binary is the classic "damaged and can't be opened" error — the fix is entitlements (com.apple.security.cs.allow-unsigned-executable-memory, sometimes disable-library-validation) plus codesign --deep after the runtime is staged. Re-verify after every runtime bump: a new binary is a new signature subject.

Windows: antivirus heuristics. A freshly built PHP executable inside an installer trips SmartScreen and some AV engines. Reputation is earned by signing the installer and the embedded binary; factor a few weeks of reputation-building into release planning. A runtime bump resets some of that goodwill — do not ship a new php-bin and a new installer certificate in the same week if you can avoid it.

Vendor size. The PHP runtime is tens of MB before your vendor/. Prune dev dependencies in the packaged app and be deliberate about what gets copied — the difference between a 60 MB and 200 MB installer is usually node_modules or test fixtures leaking into the bundle.

Path resolution is the #1 debug rabbit hole. In a packaged app, base_path() may not be what you expect relative to the runtime. Anything that resolves paths relative to __DIR__ or getcwd() is suspect. Use Laravel's path helpers and verify in a real packaged build.

Logging and crash visibility. Attach a file logger and, for early debugging, a top-level try/catch in public/index.php (NativePHP's entry) that writes the exception to a known-writable path. Silent crashes in the field are almost always a PHP runtime issue, not a Laravel one.

Extension points: fork, don't patch. If you need a non-default extension or a newer PHP version, the supported move is a maintained fork of php-bin or an upstream build request — not editing the resolved artifact in vendor/. Local edits get blown away on the next composer update. The upstream extension list is genuinely responsive (sodium arrived this cycle), so file the request before you fork.

Keep a reproducible runtime. Commit the resolved nativephp/php-bin version and your platform pin. When a support ticket says "v1.2.3 crashes on Windows 11," the first question is which PHP runtime did that build ship — and only a pinned lockfile answers it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource