fatlum / nativephp-barcode-reader
Free QR code and barcode reading from image files for NativePHP Mobile v4: Apple Vision on iOS, ML Kit on Android. Works where PHP QR libraries cannot, because the PHP runtime on the phone has no GD or Imagick.
Package info
github.com/FatlumGjinofci/nativephp-barcode-reader
Type:nativephp-plugin
pkg:composer/fatlum/nativephp-barcode-reader
Requires
- php: ^8.3
- nativephp/mobile: ^4.4
Requires (Dev)
- orchestra/testbench: ^10.0|^11.0
- phpunit/phpunit: ^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A free, MIT-licensed plugin for NativePHP Mobile v4 that reads QR codes and barcodes from an image file on the device: a screenshot, a ticket photo, or anything the user picks from Photos.
PHP QR libraries cannot do this on the phone: the PHP runtime NativePHP ships has no GD and no Imagick, so they cannot read pixels. This plugin decodes natively instead:
| Platform | Decoder |
|---|---|
| iOS | Apple Vision (VNDetectBarcodesRequest), with Core Image's QR detector as a fallback |
| Android | ML Kit Barcode Scanning (bundled model, works offline) |
Compatibility
nativephp/mobile |
Status |
|---|---|
^4.4 |
Supported (tested on 4.4 and 4.6) |
< 4.4 |
Not supported |
PHP 8.3+, Laravel 12 or 13, iOS 15+, Android API 26+.
What's implemented
- One synchronous call: the result comes back from the bridge, not as an event.
- PNG, JPEG and HEIC (iOS), with EXIF orientation applied, so portrait photos work.
- Large camera originals are downscaled to 3000 px on the longest side before decoding, so a 50 MP photo never allocates a full-size bitmap.
- Every code in the picture, largest first, so you can skip codes your app cannot use.
- UPC-A is reported the same way on both platforms (
upca, 12 digits); Vision would otherwise report it as a 13-digit EAN-13.
This plugin reads codes from images. It does not open a live camera scanner.
Install
composer require fatlum/nativephp-barcode-reader
php artisan vendor:publish --tag=nativephp-plugins-provider # once per app, if not done yet
php artisan native:plugin:register fatlum/nativephp-barcode-reader
Developing the plugin next to your app
Clone it into a sibling folder and install it from there through a path repository; Composer symlinks it, so edits show up in the app immediately:
composer config repositories.nativephp-barcode-reader '{"type": "path", "url": "../nativephp-barcode-reader", "options": {"symlink": true}}'
composer require fatlum/nativephp-barcode-reader:@dev
php artisan native:plugin:register fatlum/nativephp-barcode-reader
Usage
use Lumi\NativeBarcodeReader\Facades\BarcodeReader; // e.g. the path from Camera::pickImages()'s MediaSelected event $code = BarcodeReader::read($path); if ($code === null) { // no code found, unreadable image, or not running on a device } else { $code['value']; // "PF-00482193" $code['format']; // "qr", "aztec", "pdf417", "code128", "ean13", "ean8", "upca", "upce", // "code39", "code93", "itf", "datamatrix" or "codabar" } // Every code in the picture, largest first foreach (BarcodeReader::readAll($path) as $code) { // ... } BarcodeReader::isAvailable(); // false in the browser or when the plugin is not compiled in
$path may be an absolute path or a file:// URL (Android also accepts content://).
Picking a photo and reading its code
use Lumi\NativeBarcodeReader\Facades\BarcodeReader; use Native\Mobile\Attributes\On; use Native\Mobile\Events\Gallery\MediaSelected; use Native\Mobile\Facades\Camera; public function codeFromPhoto(): void { Camera::pickImages('image')->id('code')->start(); // needs nativephp/mobile-camera } #[On(MediaSelected::class)] public function onMediaSelected(bool $success, array $files = [], ?string $id = null): void { $path = $files[0]['path'] ?? null; $code = $success && $path ? BarcodeReader::read($path) : null; // ... }
JavaScript (Vue, React, Inertia, web-view apps)
Livewire, Blade and NativeComponent screens use the PHP facade above. Apps that call native
code from JavaScript can import the helpers shipped in resources/js/barcodeReader.js:
import { read, readAll } from '../../vendor/fatlum/nativephp-barcode-reader/resources/js/barcodeReader.js'; const code = await read(path); // { value: 'PF-00482193', format: 'qr' } or null const codes = await readAll(path); // [{ value, format }, ...] largest first
They post to NativePHP's /_native/api/call route (sending the csrf-token meta tag when the
page has one) and, like the PHP facade, never throw: no code, an unreadable image, a missing
plugin or no device all resolve to null / [].
AI guidelines (Laravel Boost)
The plugin ships Boost guidelines in resources/boost/guidelines/core.blade.php. Apps that use
Laravel Boost pick them up on php artisan boost:install, so
AI assistants use this plugin, not a PHP QR library, to read codes on the phone.
Bridge function
| Name | Parameters | Returns |
|---|---|---|
BarcodeReader.Read |
path |
{found, value?, format?, codes: [{value, format}]}, largest code first; an error response when the image cannot be read |
Testing in your app
use Native\Mobile\Testing\Native; Native::fakeBridge()->respondTo('BarcodeReader.Read', [ 'found' => true, 'value' => 'PF-00482193', 'format' => 'qr', ]);
Developing
composer install composer test # PHPUnit: PHP facade and manifest composer test:js # Node's test runner: JavaScript helpers (Node 22+)
GitHub Actions runs both on every push and pull request: PHP 8.3 and 8.4 against Laravel 12 and 13, plus the JavaScript tests.
The native Swift and Kotlin code has no automated tests; check it on real devices before a
release (php artisan native:run ios / native:run android in an app that uses the plugin).
On the iOS simulator Vision cannot run ("Could not create inference context"), so only QR codes
are read there, through Core Image.
License
MIT