PHPackages                             ryangjchandler/orbit - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. ryangjchandler/orbit

ActiveLibrary[Database &amp; ORM](/categories/database)

ryangjchandler/orbit
====================

A flat-file database driver for Eloquent.

v1.4.3(2mo ago)922256.2k↑53.9%39[7 issues](https://github.com/ryangjchandler/orbit/issues)[2 PRs](https://github.com/ryangjchandler/orbit/pulls)5MITPHPPHP ^8.2CI passing

Since Mar 21Pushed 2mo ago8 watchersCompare

[ Source](https://github.com/ryangjchandler/orbit)[ Packagist](https://packagist.org/packages/ryangjchandler/orbit)[ GitHub Sponsors](https://github.com/ryangjchandler)[ RSS](/packages/ryangjchandler-orbit/feed)WikiDiscussions 1.x Synced 1mo ago

READMEChangelog (10)Dependencies (26)Versions (51)Used By (5)

[![Orbit](./art/orbit.png)](./art/orbit.png)

 [![Laravel v9.x](https://camo.githubusercontent.com/25242f3980f58cac4761477eeb8aaf08f483af9313019d7df7bc07fc42deea69/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d76392e782d4646324432303f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c)](https://laravel.com) [![PHP 8.0](https://camo.githubusercontent.com/2091ef06611f32d698bc7cc9a7331556f251f26d41ee5820639e6acabbe77ad0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e302d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870)](https://php.net)

Orbit is a flat-file driver for Laravel Eloquent. It allows you to replace your generic database with real files that you can manipulate using the methods you're familiar with.

Installation
------------

[](#installation)

To install Orbit, run the following command in your project:

```
composer require ryangjchandler/orbit
```

Usage
-----

[](#usage)

To begin using Orbit, create a Laravel model and use the `Orbit\Concerns\Orbital` trait.

```
class Post extends Model
{
    use \Orbit\Concerns\Orbital;
}
```

The `Orbital` trait is responsible for hooking into the Eloquent lifecycle and ensuring all of your interactions are handled correctly.

### Defining the Schema

[](#defining-the-schema)

Just like a database migration, you need to define the different pieces of data that your Orbit model can have. Add a `public static function schema(Blueprint $table)` method to your model.

This method will need to accept an instance of `Illuminate\Database\Schema\Blueprint`, just like a migration.

```
use Illuminate\Database\Schema\Blueprint;

class Post extends Model
{
    use \Orbit\Concerns\Orbital;

    public static function schema(Blueprint $table)
    {
        $table->string('title');
        $table->string('slug');
        $table->timestamp('published_at');
    }
}
```

> If some of your data is optional, make sure the corresponding column is `nullable`.

### Storing content

[](#storing-content)

By default, all content is stored inside of a `content` folder in the root of your application. If you wish to change this, publish the `orbit.php` configuration file and change the `orbit.paths.content` option.

Orbit will transform the base name of your model into a pluralized snake-cased string and use that as the main folder name, e.g. `Post` -&gt; `content/posts`, `PostCategory` =&gt; `content/post_categories`.

> 🚨 Changing the name of a model will prevent Orbit from finding any existing records in the old folder. If you wish to change the name of the folder, overwrite the `public static function getOrbitalName` method on your model class and return the old name instead.

Any time you call `Model::create()`, `Model::update` or `Model::delete`, Orbit will intercept those calls and forward to the necessary driver method. The driver is then responsible for performing the necessary file system calls.

### Changing the primary key

[](#changing-the-primary-key)

Just like a normal Eloquent model, you can change the primary key of your Orbit model. Overwrite the `Model::getKeyName` method and return the name of your new model.

```
class Post extends Model
{
    use Orbital;

    public function getKeyName()
    {
        return 'slug';
    }

    public function getIncrementing()
    {
        return false;
    }
}
```

> If your model's primary key (the key you defined in `getKeyName`) doesn't need to automatically increment, you should either define `public $incrementing = false` on the model or overwrite the `getIncrementing` method.

Standard Orbit drivers will respect the new key name and use that when creating, updating and deleting files on disk, e.g. a `Post` with the slug `hello-world` will write to the `content/posts/hello-world.md` file.

> 🚨 Changing the key for a model after records already exist can cause damage. Be sure to rename your files afterwards so that Orbit doesn't create duplicate content.

### Soft Deletes

[](#soft-deletes)

Since Orbit needs to update files on disk when your model is updated, the standard Eloquent `SoftDeletes` trait doesn't quite work. If you want to add soft delete support to your Orbit model, you can instead use the `Orbit\Concerns\SoftDeletes` trait.

This trait uses the Eloquent one under-the-hood, so you can still access all of your normal `SoftDeletes` methods, including `isForceDeleting()` and `forceDelete()`.

The Orbit version adds in the necessary hooks to perform file system operations as well as ensure you don't completely delete your content.

### Validation Rules

[](#validation-rules)

When dealing with [validation rules](https://laravel.com/docs/8.x/validation#available-validation-rules) that check against a database like [`exists`](https://laravel.com/docs/8.x/validation#rule-exists) and [`unique`](https://laravel.com/docs/8.x/validation#rule-unique), you should use the **fully-qualified namespace (FQN) of the model** instead of the table name.

This is because Orbit runs on a separate database connection - using the FQN will allow Laravel to correctly resolve the qualified table name.

```
class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'slug' => 'required|alpha_dash|unique:App\Post,id',
            // 'slug' => ['required', 'alpha_dash', Rule::unique(Post::class)],
            'title' => 'required',
            'description' => 'required',
        ];
    }
  }
```

### Testing

[](#testing)

As previously mentioned in the [Validation Rules](#validation-rules) section, Orbit operates on a custom connection called `orbit`. This means that Laravel's database testing utilities will work, as long as you specify the connection name.

```
$this->assertDatabaseCount('posts', 5, 'orbit');

$this->assertDatabaseHas('posts', [
    'title' => 'Hello, world',
    'slug' => 'hello-world',
], 'orbit');
```

Drivers
-------

[](#drivers)

Orbit is a driver-based package, making it very easy to change the storage format of your data.

Out of the box, Orbit provides the following drivers:

- `md` -&gt; `Orbit\Drivers\Markdown`
- `json` =&gt; `Orbit\Drivers\Json`
- `yaml` =&gt; `Orbit\Drivers\Yaml`

### `md`

[](#md)

This is a Markdown that is capable of parsing Markdown files, as well as YAML front-matter.

When Orbit loads files using this driver, it will map each front-matter key into a column in your models `schema`.

By default, the Markdown driver will also add a `TEXT content` column to your schema. This is used to store the Markdown body from the file.

> 💡 If you wish to customise the name of the `content` column, you can use the `Markdown::contentColumn()` method and provide a new column name. This is applied to all models that use the `Markdown` driver.

### `json`

[](#json)

This is a JSON driver that is capable of parsing `.json` files. Each key in the file is mapped to a column in your schema.

### `yaml`

[](#yaml)

This is a YAML driver that is capable of parsing `.yml` files. Each key in the file is mapped to a column in your schema.

### Registering drivers

[](#registering-drivers)

You can register custom Orbit drivers by using the `Orbit::extend` method. You should call this method from the `boot` method in a `ServiceProvider`.

```
\Orbit\Facades\Orbit::extend('json', function ($app) {
    return new \App\Drivers\JsonDriver($app);
})
```

All drivers must implement the `Orbit\Contracts\Driver` contract, or extend the `Orbit\Drivers\FileDriver` class. This enforces drivers to have at least 4 methods:

```
interface Driver
{
    public function shouldRestoreCache(string $directory): bool;

    public function save(Model $model, string $directory): bool;

    public function delete(Model $model, string $directory): bool;

    public function all(string $directory): Collection;
}
```

Here is what each method is used for:

- `shouldRestoreCache` - used to determine if the file cache should be updated.
- `save` - used to persist model changes to a file on disk, or create a new file.
- `delete` - used to delete an existing file on disk
- `all` - used to retrieve all records from disk and cache.

### Extending `FileDriver`

[](#extending-filedriver)

Extending the `Orbit\Drivers\FileDriver` class is useful when you want some of the heavy lifting done for you. To work with this base class, you should do the following:

1. Implement an `extension(): string` method that returns the file extension as a string, i.e. `return 'md'` for `Markdown`.
2. Implement a `dumpContent(Model $model): string` method. This method should return the updated content for the file.
3. Implement a `parseContent(SplFileInfo $file): array` method. This method should return an array of `key => value` pairs, where each `key` is a column in the `schema`.

### Changing drivers

[](#changing-drivers)

If you wish to use a different driver for one of your models, you can add a `public static $driver` property to your model and set the value to the name of a driver.

```
class Post extends Model
{
    use Orbital;

    public static $driver = 'json';
}
```

> Driver names are determined when they are registered with Orbit. You should always use the string name of the driver instead of the fully-qualified class name.

### Disabling Orbit

[](#disabling-orbit)

If you have a model that uses the `Orbital` trait and would like to temporarily disable Orbit's functionality, you can override the `enableOrbit(): bool` method on your model:

```
class Post extends Model
{
    use Orbital;

    public static function enableOrbit(): bool
    {
        return false;
    }
}
```

###  Health Score

67

—

FairBetter than 100% of packages

Maintenance88

Actively maintained with recent releases

Popularity57

Moderate usage in the ecosystem

Community32

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 85.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~38 days

Recently: every ~0 days

Total

48

Last Release

60d ago

Major Versions

v1.1.3 → v2.0.0-beta12022-05-09

v1.2.1 → v2.0.0-beta22023-10-04

v1.3.0 → v2.0.0-beta52024-04-14

v1.4.1 → v2.0.0-beta72025-09-01

v1.4.2 → v2.0.0-rc12026-03-18

PHP version history (5 changes)v0.5.1PHP ^7.4 || ^8.0

v1.0.0PHP ^8.0

v2.0.0-beta1PHP ^8.1

v2.0.0-beta2PHP ^8.2

v2.0.0-rc1PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/568d485d441c691b0358b9091254a6a671fef8f76b73f28af1180ad568d142b2?d=identicon)[ryangjchandler](/maintainers/ryangjchandler)

---

Top Contributors

[![ryangjchandler](https://avatars.githubusercontent.com/u/41837763?v=4)](https://github.com/ryangjchandler "ryangjchandler (225 commits)")[![jwpage](https://avatars.githubusercontent.com/u/52687?v=4)](https://github.com/jwpage "jwpage (8 commits)")[![Gummibeer](https://avatars.githubusercontent.com/u/6187884?v=4)](https://github.com/Gummibeer "Gummibeer (7 commits)")[![stancl](https://avatars.githubusercontent.com/u/33033094?v=4)](https://github.com/stancl "stancl (6 commits)")[![theutz](https://avatars.githubusercontent.com/u/756348?v=4)](https://github.com/theutz "theutz (4 commits)")[![Jubeki](https://avatars.githubusercontent.com/u/15707543?v=4)](https://github.com/Jubeki "Jubeki (2 commits)")[![ousid](https://avatars.githubusercontent.com/u/21012933?v=4)](https://github.com/ousid "ousid (2 commits)")[![erickpatrick](https://avatars.githubusercontent.com/u/396013?v=4)](https://github.com/erickpatrick "erickpatrick (1 commits)")[![ukjadoon](https://avatars.githubusercontent.com/u/549181?v=4)](https://github.com/ukjadoon "ukjadoon (1 commits)")[![happytodev](https://avatars.githubusercontent.com/u/425998?v=4)](https://github.com/happytodev "happytodev (1 commits)")[![joelclermont](https://avatars.githubusercontent.com/u/298100?v=4)](https://github.com/joelclermont "joelclermont (1 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (1 commits)")[![phuclh](https://avatars.githubusercontent.com/u/6707194?v=4)](https://github.com/phuclh "phuclh (1 commits)")[![riesjart](https://avatars.githubusercontent.com/u/23455176?v=4)](https://github.com/riesjart "riesjart (1 commits)")[![shuvroroy](https://avatars.githubusercontent.com/u/21066418?v=4)](https://github.com/shuvroroy "shuvroroy (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ryangjchandler-orbit/health.svg)

```
[![Health](https://phpackages.com/badges/ryangjchandler-orbit/health.svg)](https://phpackages.com/packages/ryangjchandler-orbit)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k7.2M71](/packages/mongodb-laravel-mongodb)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)[cybercog/laravel-ban

Laravel Ban simplify blocking and banning Eloquent models.

1.1k651.8k11](/packages/cybercog-laravel-ban)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
