NativePHP for mobileを触ってみた

# NativePHPについて

Laravelを基盤としてデスクトップアプリ・モバイルアプリを開発出来るフレームワークです
先にデスクトップアプリ用が2025/4に正式リリースされて2025/5/2にモバイルアプリ用が正式リリースされました
まだ出たばかりというのもありモバイルアプリ用のライセンスを購入する必要があります

https://nativephp.com

# 必要要件

* PHP 8.3以上
* Laravel 10以上

## iOS向け要件
* macOS 12以上のApple Silicon Mac
* XCode 16以上

## Android向け要件
* `java -v`と`adb devices`がターミナルで実行できること
* (Windowsの場合は) 7zipのインストール

## 環境変数の設定

### macOSの場合
```zsh
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$JAVA_HOME/bin:$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools
```

### Windowsの場合
```zsh
set ANDROID_HOME=C:\Users\yourname\AppData\Local\Android\Sdk
set PATH=%PATH%;%JAVA_HOME%\bin;%ANDROID_HOME%\platform-tools
set JAVA_HOME=C:\Program Files\Microsoft\jdk-17.0.8.7-hotspot
```

設定出来たらターミナルの再起動などを行ってください

# 環境構築

## ディレクトリ構成
```zsh
nativephp/
├── docker/
│   ├── php/
│   │   └── Dockerfile
│   └── nginx/
│       └── default.conf
├── .env
├── docker-compose.yml
└── src/
```

### docker-compose.yml
```yml:docker-compose.yml
services:
  app:
    build:
      context: ./docker/php
    container_name: laravel_app
    volumes:
      - ./src:/var/www
    working_dir: /var/www
    ports:
      - "9000:9000"
    depends_on:
      - mysql

  web:
    image: nginx:latest
    container_name: nginx
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app

  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: unless-stopped
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: laravel
    volumes:
      - db_data:/var/lib/mysql

  node:
    image: node:22
    container_name: node
    working_dir: /var/www
    volumes:
      - ./src:/var/www
    tty: true

volumes:
  db_data:
```

### Dockerfile
```Dockerfile:docker/php/Dockerfile
FROM php:8.3-fpm

RUN apt-get update && apt-get install -y \
  git zip unzip curl libzip-dev libpng-dev libonig-dev libxml2-dev \
  && docker-php-ext-install pdo_mysql mbstring zip exif pcntl

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www
```

### default.conf
```conf:docker/nginx/default.conf
server {
  listen 80;
  index index.php index.html;
  root /var/www/public;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {
    fastcgi_pass app:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    fastcgi_param DOCUMENT_ROOT $realpath_root;
  }

  location ~ /\.ht {
    deny all;
  }
}
```

### Laravel環境構築
```zsh:zsh
docker compose run --rm app composer create-project laravel/laravel .
```

### 起動
```zsh:zsh
docker compose up -d
```
起動して問題なくwebからアクセス出来るか確認をします

[http://localhost:8080/](http://localhost:8080/)
![CleanShot 2025-06-01 at 18.50.22@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/dbff57e3-67d1-438a-9b3b-066741957e53.png)

### ライセンス購入

ここからラインセンスを購入します
購入するプランはご自身で選んでください
https://nativephp.com/mobile
![CleanShot 2025-06-01 at 18.51.18@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/c93f97c1-46ec-4b91-b341-4fd4dd0c3d42.png)

登録し続ければ下記画面まで進める事ができます
ライセンスキーは誰もにも教えずメモしておいてください

![CleanShot 2025-06-01 at 18.52.34@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/02066267-532e-4fe8-97aa-0398eb7f2d0d.png)

### .envに追記
:::note warn
`NATIVEPHP_APP_ID`のvalueをデフォルトの`com.nativephp.yourapp`だとエラーが出てしまうので`com.roll1226.roll1226app`のように設定してください
:::

```src/.env
NATIVEPHP_APP_ID="com.nativephp.yourapp"
NATIVEPHP_APP_VERSION="DEBUG"
NATIVEPHP_APP_VERSION_CODE="1"
```

### NativePHPのライブラリをインストール
#### composer.jsonに追記
```diff_json:src/composer.json
{
    ...
    "require-dev": {
        "fakerphp/faker": "^1.23",
        "laravel/pail": "^1.2.2",
        "laravel/pint": "^1.13",
        "laravel/sail": "^1.41",
        "mockery/mockery": "^1.6",
        "nunomaduro/collision": "^8.6",
        "phpunit/phpunit": "^11.5.3"
    },
+    "repositories": [
+        {
+            "type": "composer",
+            "url": "https://nativephp.composer.sh"
+        }
+    ],
    ...
}
```
#### composerでインストール
```zsh:zsh
docker compose exec app composer require nativephp/ios
```
```zsh:zsh
docker compose exec app composer require nativephp/mobile
```
１つ目のライブラリをインストールしようとすると対話モードが始まります
`Username`と`Password`を入力するよう求められます

* Username → ライセンス登録時に入力したEmail
* Password → メモしたライセンスキー

を入力してください

![CleanShot 2025-06-01 at 19.01.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/46af3747-23b7-49c7-b497-1231c15e0c42.png)

### NativePHPのインストーラーを実行
:::note warn
コンテナ内からローカルのエミュレータを起動することが難しかったためローカルからコマンドを実行するようにしています
なのでNativePHPのコマンドを実行する際はローカルでコマンドを実行するとよさそうです
:::


```zsh:zsh
cd src
php artisan native:install
```

こちらも実行すると対話モードが始まります

#### プラットフォームの選択
今回はiOSとAndroid両方を見ていきたいので`Both`を選択してください

`Include ICU-enabled PHP binary?`と聞かれるのでこちらはどちらでも構わいません

![CleanShot 2025-06-01 at 19.09.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/cd4c9de8-3958-4cab-8942-4c7a6230ac33.png)

実行が完了したら実際に実行していこうと思います

# 実行
## Android
```zsh:zsh
php artisan native:run android --build=debug
```

実行出来ればLaravelのwelcome画面が表示されます
![CleanShot 2025-06-01 at 19.13.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/7f488882-9481-4967-aca6-73ab5516b944.png)

## iOS
```zsh:zsh
php artisan native:run ios --build=debug
```

実行するとどのエミュレータで動かすか聞かれるので開発に使用するエミュレータを選んでください
![CleanShot 2025-06-01 at 19.16.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/17389e81-babc-4e57-aedd-4533bb2a1063.png)

実行出来ればLaravelのwelcome画面が表示されます
![CleanShot 2025-06-01 at 19.19.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/8342c173-edc1-4bba-acb2-1e3d7ce3b1e6.png)

# 機能実装
簡単な機能を実装していこうと思います

## livewireのインストール
NativePHPがlivewireを使用しているため今回の実装でも使用していきます

https://laravel-livewire.com/

```zsh:zsh
docker compose exec app composer require livewire/livewire
```

```diff_php:resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link rel="preconnect" href="https://fonts.bunny.net">
        <link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600" rel="stylesheet" />

+        @livewireStyles
    </head>
    <body>
+        @livewireScripts
    </body>
</html>
```
これでlivewireが使用できるようになりました

## カメラの実装
livewireを実行してファイルを作成していきます
```zsh:zsh
docker compose exec app php artisan make:livewire camera
```
作成出来たらコードを書いていきます

```diff_php:app/Livewire/Camera.php
<?php

namespace App\Livewire;

use Livewire\Component;
+use Native\Mobile\Facades\System;

class Camera extends Component
{
+    public function camera()
+    {
+       System::camera();
+    }

    public function render()
    {
        return view('livewire.camera');
    }
}
```
```diff_php:resources/views/livewire/camera.blade.php
<div>
-    {{-- The whole world belongs to you. --}}
+    <button wire:click="camera">カメラ</button>
</div>
```

```diff_php:resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link rel="preconnect" href="https://fonts.bunny.net">
        <link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600" rel="stylesheet" />

        @livewireStyles
    </head>
    <body>
        @livewireScripts
+        <livewire:camera />
    </body>
</html>
```

コードが書けたらエミュレータを実行することで確認が出来ます

![CleanShot 2025-06-01 at 19.36.39.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/3595b5f0-ff6b-4f0c-89e5-05b5af795267.gif)

## シェアの実装

livewireを実行してファイルを作成していきます
```zsh:zsh
docker compose exec app php artisan make:livewire share
```

作成出来たらコマンドを書いていきます
```diff_php:app/Livewire/Share.php
<?php

namespace App\Livewire;

use Livewire\Component;
+use Native\Mobile\Facades\Dialog;

class Share extends Component
{
+    public function share()
+    {
+        Dialog::share('Google', 'GoogleのURLをシェア', 'https://www.google.com');
+    }

    public function render()
    {
        return view('livewire.share');
    }
}
```

```diff_php:resources/views/livewire/share.blade.php
<div>
-    {{-- The whole world belongs to you. --}}
+    <button wire:click="share">シェア</button>
</div>
```

```diff_php:resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link rel="preconnect" href="https://fonts.bunny.net">
        <link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600" rel="stylesheet" />

        @livewireStyles
    </head>
    <body>
        @livewireScripts
        <livewire:camera />
+        <livewire:share />
    </body>
</html>
```

コードが書けたらエミュレータを実行することで確認が出来ます
![CleanShot 2025-06-01 at 19.52.25.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/7e9dc3bb-defe-4cc5-8c37-75aafc934708.gif)

# 使ってみて
NativePHP for mobileを使ってみた感想ですが「まだ実用は難しいのでは」と感じました
現状ライセンスが有料なのでReactNativeやFlutterを採用する流れになるかと思います(今後、無料になる可能性があると公式は出しています)
またNativePHP for mobileの情報が少ないので開発には難航するかと思いますので無理やり開発に採用する必要はないです
ですが、面白い取り組みなので今後も追っていこうと思います