Belajar NativePHP - Database Offline: SQLite + Eloquent
Episode 10 of 28

Belajar NativePHP - Database Offline: SQLite + Eloquent

Mengelola database SQLite di perangkat dengan Eloquent ORM dan migration Laravel: CRUD offline-first, konfigurasi database, strategi sinkronisasi ketika online, serta repository pattern untuk data catatan offline.

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 9 kita mengakses GPS, haptic feedback, dan clipboard, pada episode ini kita masuk ke database offline: cara menyimpan data di perangkat menggunakan SQLite yang dikelola oleh Eloquent ORM dan migration Laravel. Ini adalah inti dari arsitektur offline-first — aplikasi berfungsi tanpa koneksi internet, dan data disinkronkan ke server saat online.

SQLite adalah pilihan ideal untuk mobile: tanpa server, zero-configuration, dan sudah terbundel di iOS & Android. Dengan Eloquent, kalian menggunakan syntax Laravel yang sama persis — hanya beda di konfigurasi koneksi.

Konfigurasi SQLite di NativePHP

config/database.php
<?php
 
return [
    'default' => env('DB_CONNECTION', 'sqlite'),
 
    'connections' => [
        'sqlite' => [
            'driver' => 'sqlite',
            // NativePHP menggunakan path relatif ke app bundle
            'database' => database_path('database.sqlite'),
            'prefix' => '',
            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
        ],
    ],
];

Di NativePHP, database_path() meresol ke direktori writable di dalam app bundle. SQLite database dibuat otomatis jika belum ada — tidak perlu setup server atau kredensial.

Migration Laravel

Gunakan migration yang sama persis seperti web:

Buat migration untuk catatan
php artisan make:migration create_notes_table
database/migrations/xxxx_create_notes_table.php
<?php
 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('notes', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->boolean('completed')->default(false);
            $table->timestamp('synced_at')->nullable();
            $table->timestamps();
        });
    }
 
    public function down(): void
    {
        Schema::dropIfExists('notes');
    }
};

Perhatikan kolom synced_at — ini adalah flag yang menandai apakah record sudah disinkronkan ke server. Kita gunakan ini di strategi sync episode 15.

Jalankan migration
php artisan migrate

Eloquent: CRUD Offline

Eloquent berfungsi persis seperti biasa — tetapi semua operasi terjadi di SQLite lokal:

app/Models/Note.php
<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Note extends Model
{
    protected $fillable = ['title', 'content', 'completed', 'synced_at'];
 
    public function markUnsynced(): void
    {
        $this->update(['synced_at' => null]);
    }
 
    public function markSynced(): void
    {
        $this->update(['synced_at' => now()]);
    }
 
    public function scopeUnsynced($query)
    {
        return $query->whereNull('synced_at');
    }
}

Operasi CRUD

CRUD operations di SQLite lokal
<?php
 
use App\Models\Note;
 
// Create
$note = Note::create([
    'title' => 'Belajar NativePHP',
    'content' => 'Episode 10: Database offline',
]);
 
// Read
$notes = Note::where('completed', false)->get();
$note = Note::find(1);
 
// Update
$note->update(['completed' => true]);
 
// Delete
$note->delete();

Semua operasi ini berjalan offline — tidak ada koneksi internet yang dibutuhkan. Karena SQLite berjalan di perangkat, kecepatan operasi sangat tinggi bahkan untuk ribuan record.

Repository Pattern untuk Data Layer

Untuk aplikasi yang lebih besar, gunakan repository pattern untuk memisahkan logic bisnis dari akses data:

app/Repositories/NoteRepository.php
<?php
 
namespace App\Repositories;
 
use App\Models\Note;
 
class NoteRepository
{
    public function getUnsynced(): \Illuminate\Database\Eloquent\Collection
    {
        return Note::unsynced()->get();
    }
 
    public function create(array $data): Note
    {
        return Note::create($data);
    }
 
    public function markSynced(array $ids): void
    {
        Note::whereIn('id', $ids)->update([
            'synced_at' => now(),
        ]);
    }
 
    public function getPendingCount(): int
    {
        return Note::unsynced()->count();
    }
}

Repository ini menjadi titik pusat semua operasi data — memudahkan testing, refactor, dan strategi sync yang akan kita bahas nanti.

Strategi Offline-First

Prinsip offline-first: app harus berfungsi tanpa internet, bukan "app berhenti saat offline":

100%
  1. Input user → langsung simpan ke SQLite.
  2. UI update → responsif tanpa menunggu network.
  3. Sync → saat online, kirim data ke server dan update synced_at.
  4. Conflict resolution → jika data berubah di server dan lokal, gunakan timestamp atau last-write-wins.

Tip

Selalu tampilkan indikator status: "Online" atau "Offline — X catatan perlu disinkronkan". User perlu tahu apakah data mereka sudah aman di server atau masih lokal.

Penutup

Inti yang harus dibawa pulang:

  • SQLite adalah database offline ideal: zero-config, zero-server, terbundel di iOS & Android.
  • Eloquent & migration berfungsi persis sama — hanya beda konfigurasi koneksi.
  • Kolom synced_at menandai record yang belum disinkronkan.
  • Repository pattern memisahkan data layer dari logic bisnis.
  • Offline-first: simpan ke SQLite dulu, sync ke server saat online.

Di episode 11 selanjutnya, kita akan membahas Proses Background & Persistent Mode — bagaimana PHP runtime tetap hidup, menjalankan background task, polling, dan perbedaan background execution antara iOS dan Android. Sampai jumpa di episode 11!