darkterminal/turso-php-installer
Install Turso's libSQL server binaries for PHP and Laravel with a single Composer command. Handles downloads, platform detection, and setup so you can start building with local Turso databases right away.
Minimum viable path for a Laravel dev:
php-dev headers, gcc/make, and (on Linux) the libsql C library. It is not a pure-PHP package, so composer install alone won't get you a working driver.composer require --dev darkterminal/turso-php-installer (dev-only — it ships a CLI installer, not runtime code).vendor/bin/turso-php-installer (or php vendor/darkterminal/turso-php-installer/install.php). It compiles/downloads the turso extension into your extension dir.extension=turso.so (or turso) to your php.ini / conf.d file. Restart PHP-FPM / Octane if applicable.php --ri turso and php -m | grep -i turso.$db = turso_connect(getenv('TURSO_DATABASE_URL'), getenv('TURSO_AUTH_TOKEN'));
$rows = turso_query($db, 'select * from users limit 10');
For a Laravel app, the realistic first target is a read-only reporting feature or a lightweight edge-cache database, not a wholesale swap of your primary connection — because you'll need custom glue (see below) before Eloquent works.
Where to look first: the extension's function list (php --ri turso), the Turso docs for turso db tokens create, and the installer script itself — it's a shell/PHP wrapper, so read it before running it in CI so you know what it downloads and where it puts the .so.
1. Docker/CI build step, not host install. The installer is meant to run in a reproducible build stage. Bake the extension into your php:8.3-fpm image:
RUN apt-get update && apt-get install -y gcc make autoconf pkg-config php-dev \
&& pecl install channel://pecl.php.net/... # or run the installer script
&& docker-php-ext-enable turso
Cache the resulting .so in CI so each pipeline doesn't recompile.
2. Config as a first-class connection. Add a turso connection array in config/database.php:
'turso' => [
'driver' => 'turso',
'url' => env('TURSO_DATABASE_URL'),
'token' => env('TURSO_AUTH_TOKEN'),
'sync' => env('TURSO_EMBEDDED_SYNC', false),
],
Then either write a Connection-flavored wrapper or use a community libsql PDO shim on top of the extension. There is no shipped ServiceProvider, so this wiring is yours to own.
3. Custom connector, not PDO. The extension exposes procedural functions, not a PDO implementation. To get Eloquent you'll write:
Illuminate\Database\Connection subclass wrapping turso_connect/turso_queryConnectionResolver registration in a service providerQueryGrammar if you want migrations to runRealistically, teams use it for raw queries and one small read model, keeping Eloquent on SQLite/MySQL/Postgres.
4. Embedded replica pattern. For latency-sensitive reads, sync a local replica and read from disk:
$db = turso_connect('file:./storage/turso.db', env('TURSO_AUTH_TOKEN'), $syncUrl);
turso_sync($db); // pull latest from primary before serving read-heavy pages
Trigger turso_sync() in a scheduled job (php artisan schedule:run) or on cache-miss, not on every request.
5. Token lifecycle. Mint per-environment tokens with turso db tokens create, store in your secret manager, and rotate on a schedule. Use a Config::set middleware or a small TursoTokenProvider service so tests can stub it.
6. Deployment hook. php artisan migrate should not target Turso unless you've written the connector + grammar. Use the Turso CLI or a separate artisan command (php artisan turso:migrate) that runs raw DDL through the extension — keeps prod migrations predictable.
ServiceProvider, no Facade, no Driver — it's a build helper for a native extension. The score (0.42) reflects that; budget for glue code before anything "just works."composer install is not php artisan-ready. The extension lives at the PHP binary level. If your app runs under Octane/Swoole, you must restart workers after installing/reinstalling, or they'll never see the symbol.Unable to load dynamic library). Pin the PHP version in Docker and recompile together.PDO = no Query Builder. Every DB::table(...) call will fail until you implement the connection. Debugging tip: run DB::connection('turso')->select(...) with raw SQL first to isolate whether it's your connector or the network.turso_batch or equivalent), and don't rely on DB::transaction() semantics.turso_sync() returning successfully doesn't mean you're current if the primary has unflushed writes. Read-after-write consistency needs you to route those reads to the primary.php --ri turso is your first line of defense — it prints the loaded version and dependency paths; if it errors, the .so is loaded but the libsql shared object isn't found (LD_LIBRARY_PATH / ldconfig).turso db shell for debugging. Lean on those rather than reimplementing sync logic in PHP.config/database.php you can flip via env.How can I help you explore Laravel packages today?