ryangjchandler/orbit
Orbit is a flat-file driver for Laravel Eloquent. Store model records as files instead of a database while keeping familiar Eloquent create, update, delete, and query workflows. Define a schema on your model, and Orbit handles paths and persistence automatically.
Installation:
composer require ryangjchandler/orbit
Configure config/database.php:
'connections' => [
'orbit' => [
'driver' => 'orbit',
'path' => database_path('orbit'),
],
],
Run migrations:
php artisan orbit:migrate
(Creates the database/orbit directory with users.json and migrations.json.)
First query:
use App\Models\User;
$user = User::create(['name' => 'John', 'email' => 'john@example.com']);
$users = User::all(); // Returns Collection from JSON files
Replace a legacy flat-file system (e.g., JSON/CSV) with Eloquent ORM:
// Before: Manual JSON file handling
$users = json_decode(file_get_contents('data/users.json'), true);
// After: Eloquent ORM
$users = User::all()->toArray();
Orbit auto-generates a JSON file per model (e.g., users.json, posts.json).
Example:
// Posts will use `posts.json`
Post::create(['title' => 'Hello Orbit']);
Use Laravel migrations to define structure:
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->timestamps();
});
php artisan orbit:migrate after adding new migrations.Leverage Laravel’s seeder:
public function run()
{
User::create(['name' => 'Admin', 'email' => 'admin@example.com']);
}
orbit:seed, not migrate.Use Eloquent query builders as usual:
// Soft deletes (if enabled in model)
User::withTrashed()->get();
// Relationships
$posts = User::find(1)->posts;
Override default paths per model:
class Product extends Model
{
protected $connection = 'orbit';
public $orbitPath = 'custom/products.json';
}
Enable caching for performance:
// In config/orbit.php
'cache' => true,
orbit:model:query_hash.Hook into Orbit events (e.g., orbit.saving, orbit.deleted):
// app/Providers/OrbitEventServiceProvider.php
public function boot()
{
Orbit::saving(function ($model) {
logger()->info("Saving {$model->getTable()}: {$model->id}");
});
}
Use Orbit facade to reset data:
public function tearDown(): void
{
Orbit::reset();
}
File Permissions:
storage/database/orbit is writable.chmod -R 775 storage/database/orbit.Soft Deletes:
use SoftDeletes; in model and deleted_at in migration.withTrashed() won’t work without proper setup.Concurrent Writes:
DB::transaction()).'cache' => false in config).Large Files:
users_1.json, users_2.json).orbit.path to point to a mounted network drive.Timestamps:
created_at/updated_at by default. Override in migration:
$table->timestamp('custom_created_at')->useCurrent();
Model Events:
saved()/deleted() events fire after file writes. Use saving()/deleting() for pre-actions.Check File Contents:
cat database/orbit/users.json
Enable Logging:
// config/orbit.php
'debug' => true,
storage/logs/orbit.log.Validate Migrations:
php artisan orbit:schema:dump to regenerate files from migrations.Clear Cache:
php artisan cache:clear
php artisan orbit:clear-cache
Custom Drivers:
Override OrbitServiceProvider to add support for YAML/CSV:
Orbit::extend('yaml', function () {
return new YamlDriver();
});
Encryption: Use Laravel’s encryption for sensitive fields:
$user->password = Crypt::encrypt($request->password);
$user->save();
Backup Strategy:
orbit:backup to compress files:
zip -r orbit_backup.zip database/orbit
Performance:
Orbit::preload('users');
Multi-Tenant:
Use orbit.path dynamically:
public function getOrbitPath($table)
{
return "orbit/{$this->tenantId}/{$table}.json";
}
How can I help you explore Laravel packages today?