Building NativePHP for Mobile: Compiling Laravel for iOS and Android

Overview

for Mobile represents a shift in how we think about cross-platform development. Traditionally,
PHP
and
Laravel
developers were confined to the server or, more recently, the desktop via
Electron
. This technique allows you to package a full PHP environment, including your Laravel application, directly into a native mobile binary.

This matters because it bridges the gap between web expertise and mobile functionality. Instead of learning

or
Kotlin
from scratch, you can use the framework you already know to build high-performance, native-feeling apps that live in the
Apple
. This tutorial explores the technical bridge—compiling PHP into a static library, embedding it in a native shell, and using custom
C
extensions to trigger device-specific features like share sheets and push notifications.

Prerequisites

Before you start building, you need a solid foundation in the following areas:

  • PHP & Laravel: Deep familiarity with the Laravel ecosystem and
    Composer
    .
  • C Basics: You don't need to be a C wizard, but understanding how header files and compilation work is vital.
  • Xcode: Basic knowledge of
    Xcode
    for managing iOS build targets and simulators.
  • CLI Tools: Comfort with the terminal, as much of the heavy lifting happens via build scripts.

Key Libraries & Tools

  • Static PHP CLI
    : An indispensable tool that enables the creation of standalone PHP binaries and static libraries. It handles the complex process of gathering dependencies like
    libcurl
    and
    OpenSSL
    .
  • NativePHP iOS Package: The specialized Laravel package that scaffolds the bridge between your PHP code and the Swift environment.
  • WKWebView: The iOS component used to render the application UI while intercepting custom protocol requests.
  • ChatGPT
    : Used as a technical co-pilot for translating complex C and Swift concepts for PHP developers.

Code Walkthrough: Compiling the Engine

The most difficult part of this process is generating an embeddable version of PHP. On a standard server, PHP is dynamic. For mobile, it must be a static library.

1. Generating the Static Library

We use the

to target the iOS architecture. This requires specific flags to ensure the binary is compatible with
ARM64
(for devices) or
x86_64
(for simulators).

./bin/spc build "curl,openssl,sqlite,mbstring,tokenizer,xml" --build-embed --os=ios

This command instructs the builder to include core extensions needed for Laravel and compile them into a .a (static library) file. This file contains the entire PHP engine, ready to be linked into a Swift project.

2. The Custom C Extension Bridge

To let PHP talk to the phone's hardware, we write a small C extension. This extension defines "no-op" (no operation) functions. They act as placeholders that PHP recognizes.

// native_php.c
PHP_FUNCTION(nativephp_share) {
    char *text;
    size_t text_len;
    if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &text, &text_len) == FAILURE) {
        return;
    }
    // This is a placeholder call that Swift will override
    nativephp_internal_share(text);
}

Inside the C code, nativephp_internal_share is defined as an empty function. The magic happens during the linking phase in Xcode, where we tell the compiler to look for the implementation of this function inside our Swift code instead.

3. Intercepting Requests with Swift

Since we aren't running

or
Apache
on an iPhone, we use a custom URL scheme handler. This allows the WKWebView to treat a URL like php://app/home as a trigger for the PHP engine.

class PHPSchemeHandler: NSObject, WKURLSchemeHandler {
    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        let request = urlSchemeTask.request
        // 1. Convert URL to a Laravel request
        // 2. Execute PHP engine with the request data
        // 3. Capture PHP output (HTML/JSON)
        // 4. Send response back to the webView
    }
}

This architecture bypasses the need for networking entirely. The "request" never leaves the device's memory. It moves from the WebView to Swift, into the embedded PHP library, through your Laravel routes, and back up the chain.

Syntax Notes

  • Zend API Patterns: When writing C extensions, you'll encounter PHP_FUNCTION and zend_parse_parameters. These are macros provided by the
    Zend Engine
    . They handle the conversion between C data types and PHP's internal zval types.
  • Swift Bridging Headers: Because we are mixing C and Swift, you must use a bridging header file (ProjectName-Bridging-Header.h). This file tells Swift which C headers are available for use in the high-level application code.
  • Custom URL Schemes: Unlike http://, the php:// scheme is non-standard. You must explicitly register it in the WKWebViewConfiguration to prevent the OS from trying to look it up on the public internet.

Practical Examples

Triggering Native Share Sheets

In your Laravel controller, you can now call a function that feels native to PHP but triggers a native iOS UI component:

public function sharePhoto(Request $request) {
    NativePHP::share("Check out this image!");
    return back();
}

This PHP call executes the C bridge, which triggers the Swift implementation of UIActivityViewController. The user sees the standard iOS share menu, even though the logic originated in a Laravel app.

Local Database Management

Instead of a remote

instance, your Laravel app uses
SQLite
stored locally in the app's Documents directory. This ensures the app works offline and feels instantaneous, as there is zero network latency for data operations.

Tips & Gotchas

  • Architecture Mismatches: A common error is trying to run a library compiled for the iOS Simulator on a physical device. Simulators use the Mac's architecture (often x86 or ARM), while devices strictly use ARM64. You must build two separate versions of the PHP static library and use an xcframework to bundle them.
  • Memory Management: PHP is designed for short-lived requests. In a mobile environment, the engine stays resident in memory. Be extra cautious with static variables in your Laravel code that could lead to memory bloat over time.
  • App Store Guidelines: Apple is strict about executing downloaded code. Since your PHP code is bundled within the binary at compile-time and not downloaded from a remote server, it generally complies with
    Apple
    Review Guidelines.
  • Automation is Key: Compiling PHP and its dependencies (like
    OpenSSL
    ) manually is a nightmare. Always use a tool like
    Static PHP CLI
    to ensure your builds are reproducible and consistent across different developer machines.
6 min read