PHPackages                             calebporzio/sushi - 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. calebporzio/sushi

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

calebporzio/sushi
=================

Eloquent's missing "array" driver.

v2.5.4(2mo ago)3.0k8.3M—1.8%187[16 issues](https://github.com/calebporzio/sushi/issues)[6 PRs](https://github.com/calebporzio/sushi/pulls)20MITPHPPHP ^7.1.3|^8.0CI passing

Since Jan 25Pushed 2mo ago39 watchersCompare

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

READMEChangelog (10)Dependencies (5)Versions (25)Used By (20)

Sushi 🍣
=======

[](#sushi-)

Eloquent's missing "array" driver.

Sometimes you want to use Eloquent, but without dealing with a database.

This Package Is Sponsorware 💰💰💰
-------------------------------

[](#this-package-is-sponsorware-)

Originally, this package was only available to my sponsors on GitHub Sponsors until I reached 75 sponsors.

Now that we've reached the goal, the package is fully open source.

Enjoy, and thanks for the support! ❤️

Learn more about **Sponsorware** at [github.com/sponsorware/docs](https://github.com/sponsorware/docs) 💰.

Requirements
------------

[](#requirements)

The [`pdo-sqlite` PHP extension](https://www.php.net/manual/en/ref.pdo-sqlite.php) must be installed on your system to use this package.

Install
-------

[](#install)

```
composer require calebporzio/sushi

```

Use
---

[](#use)

Using this package consists of two steps:

1. Add the `Sushi` trait to a model.
2. Add a `$rows` property to the model.

That's it.

```
class State extends Model
{
    use \Sushi\Sushi;

    protected $rows = [
        [
            'abbr' => 'NY',
            'name' => 'New York',
        ],
        [
            'abbr' => 'CA',
            'name' => 'California',
        ],
    ];
}
```

Now, you can use this model anywhere you like, and it will behave as if you created a table with the rows you provided.

```
$stateName = State::whereAbbr('NY')->first()->name;
```

This is really useful for "Fixture" data, like states, countries, zip codes, user\_roles, sites\_settings, etc...

### Relationships

[](#relationships)

Let's say you created a `Role` model, based on an array using Sushi, that looked like this:

```
class Role extends Model
{
    use \Sushi\Sushi;

    protected $rows = [
        ['id' => 1, 'label' => 'admin'],
        ['id' => 2, 'label' => 'manager'],
        ['id' => 3, 'label' => 'user'],
    ];
}
```

You can add a relationship to another standard model, just like you normally would:

```
class User extends Model
{
    ...

    public function role()
    {
        return $this->belongsTo(Role::class);
    }
}
```

Assuming the `users` table has a `role_id` column, you can do things like this:

```
// Grab a User.
$user = User::first();
// Grab a Role.
$role = Role::whereLabel('admin')->first();

// Associate them.
$user->role()->associate($role);

// Access like normal.
$user->role;

// Eager load.
$user->load('role');
User::with('role')->first();
```

> Note: There is one caveat when dealing with Sushi model relationships. The `whereHas` method will NOT work. This is because the two models are spread across two separate databases.

### Using database-checking validation rules

[](#using-database-checking-validation-rules)

You can even use Laravel's `exists:table,column` database checking request validation rule.

```
$data = request()->validate([
    'state' => ['required', 'exists:App\Models\State,abbr'],
]);
```

> Note: Be aware that you must use the fully-qualified namespace of the model instead of a table name. This ensures that Laravel will correctly resolve the model's connection.

### Custom Schema

[](#custom-schema)

If Sushi's schema auto-detection system doesn't meet your specific requirements for the supplied row data, you can customize them with the `$schema` property or the `getSchema()` method.

```
class Products extends Model
{
    use \Sushi\Sushi;

    protected $rows = [
        ['name' => 'Lawn Mower', 'price' => '226.99'],
        ['name' => 'Leaf Blower', 'price' => '134.99'],
        ['name' => 'Rake', 'price' => '9.99'],
    ];

    protected $schema = [
        'price' => 'float',
    ];
}
```

Advanced Usage
--------------

[](#advanced-usage)

When you need more flexibility, you can implement the `afterMigrate(BluePrint $table)` method, allowing you to customize the table after it has been created. This might be useful for adding indexes to certain columns.

```
class Products extends Model
{
    use \Sushi\Sushi;

    protected $rows = [
        ['name' => 'Lawn Mower', 'price' => '226.99'],
        ['name' => 'Leaf Blower', 'price' => '134.99'],
        ['name' => 'Rake', 'price' => '9.99'],
    ];

    protected function afterMigrate(Blueprint $table)
    {
        $table->index('name');
    }
}
```

How It Works
------------

[](#how-it-works)

Under the hood, this package creates and caches a SQLite database JUST for this model. It creates a table and populates the rows. If, for whatever reason, it can't cache a .sqlite file, it will default to using an in-memory sqlite database.

Using -&gt;getRows()
--------------------

[](#using--getrows)

You can optionally opt out of using the `protected $rows` property, and directly implement your own `getRows()` method.

This will allow you to determine the rows for the model at runtime. You can even generate the model's rows from an external source like a third-party API.

```
class Role extends Model
{
    use \Sushi\Sushi;

    public function getRows()
    {
        return [
            ['id' => 1, 'label' => 'admin'],
            ['id' => 2, 'label' => 'manager'],
            ['id' => 3, 'label' => 'user'],
        ];
    }
}
```

### Caching -&gt;getRows()

[](#caching--getrows)

If you choose to use your own -&gt;getRows() method, the rows will NOT be cached between requests by default.

You can force Sushi to cache your dataset with the following method: `sushiShouldCache()`.

Let's look at a configuration where `->getRows()` datasets would be cached as an example:

```
class Role extends Model
{
    use \Sushi\Sushi;

    public function getRows()
    {
        return [
            ['id' => 1, 'label' => 'admin'],
            ['id' => 2, 'label' => 'manager'],
            ['id' => 3, 'label' => 'user'],
        ];
    }

    protected function sushiShouldCache()
    {
        return true;
    }
}
```

By default, Sushi looks at the "last modified" timestamp of your model PHP file and compares it with its internal `.sqlite` cache file. If the model file has been changed more recently than the `.sqlite` cache file, then Sushi will destroy and rebuild the `.sqlite` cache. Additionally, you can configure an external file for Sushi to reference when determining if the cache is up to date or needs to be refreshed.

If, for example, you are using Sushi to provide an Eloquent model for an external data source file like an `.csv` file, you can use `sushiCacheReferencePath` to force Sushi to reference the `.csv` file when determining if the cache is stale.

For example:

```
class Role extends Model
{
    use \Sushi\Sushi;

    public function getRows()
    {
        return CSV::fromFile(__DIR__.'/roles.csv')->toArray();
    }

    protected function sushiShouldCache()
    {
        return true;
    }

    protected function sushiCacheReferencePath()
    {
        return __DIR__.'/roles.csv';
    }
}
```

Now, Sushi will only "bust" its internal cache if `roles.csv` changes, rather than looking at the `Role.php` model.

### Handling Empty Datasets

[](#handling-empty-datasets)

Sushi reads the first row in your dataset to work out the scheme of the SQLite table. If you are using `getRows()` and this returns an empty array (e.g an API returns nothing back) then Sushi would throw an error.

If you would like Sushi to work even if the dataset is empty, you can define your schema in the optional `protected $schema` array.

> Note: If you choose to use your own -&gt;getRows() method, the rows will NOT be cached between requests.

```
class Currency extends Model
{
    use \Sushi\Sushi;

    protected $schema = [
        'id' => 'integer',
        'name' => 'string',
        'symbol' => 'string',
        'precision' => 'float'
    ];

    public function getRows()
    {
        return [];
    }
}
```

### Handling String-based Primary Keys

[](#handling-string-based-primary-keys)

Sushi requires you to add two properties to your model, if it uses a string-based primary key - `$incrementing` and `$keyType`:

```
class Role extends Model
{
    use \Sushi\Sushi;

    public $incrementing = false;

    protected $keyType = 'string';

    protected $rows = [
        ['id' => 'admin', 'label' => 'Admin'],
        ['id' => 'manager', 'label' => 'Manager'],
        ['id' => 'user', 'label' => 'User'],
    ];
}
```

### Troubleshoot

[](#troubleshoot)

**ERROR:** `SQLSTATE[HY000]: General error: 1 too many SQL variables`

By default Sushi uses chunks of `100` to insert your data in the SQLite database. In some scenarios this might hit some SQLite limits. You can configure the chunk size in the model: `public $sushiInsertChunkSize = 50;`

###  Health Score

72

—

ExcellentBetter than 100% of packages

Maintenance83

Actively maintained with recent releases

Popularity74

Solid adoption and visibility

Community51

Growing community involvement

Maturity71

Established project with proven stability

 Bus Factor1

Top contributor holds 63.3% 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 ~105 days

Recently: every ~187 days

Total

22

Last Release

87d ago

Major Versions

v1.1.2 → v2.0.02020-03-04

PHP version history (2 changes)v1.0.2PHP ^7.1.3

v2.1.1PHP ^7.1.3|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/4608292025df3cf1d9db20c0484c7d0a3542e9a63fc681fae175e0233f1c250a?d=identicon)[calebporzio](/maintainers/calebporzio)

---

Top Contributors

[![calebporzio](https://avatars.githubusercontent.com/u/3670578?v=4)](https://github.com/calebporzio "calebporzio (76 commits)")[![joshhanley](https://avatars.githubusercontent.com/u/882837?v=4)](https://github.com/joshhanley "joshhanley (8 commits)")[![danharrin](https://avatars.githubusercontent.com/u/41773797?v=4)](https://github.com/danharrin "danharrin (3 commits)")[![ErickZH](https://avatars.githubusercontent.com/u/14044588?v=4)](https://github.com/ErickZH "ErickZH (2 commits)")[![shadoWalker89](https://avatars.githubusercontent.com/u/1449151?v=4)](https://github.com/shadoWalker89 "shadoWalker89 (2 commits)")[![Flynsarmy](https://avatars.githubusercontent.com/u/334808?v=4)](https://github.com/Flynsarmy "Flynsarmy (2 commits)")[![morpheus7CS](https://avatars.githubusercontent.com/u/8884582?v=4)](https://github.com/morpheus7CS "morpheus7CS (2 commits)")[![incredimike](https://avatars.githubusercontent.com/u/125589?v=4)](https://github.com/incredimike "incredimike (2 commits)")[![inmanturbo](https://avatars.githubusercontent.com/u/47095624?v=4)](https://github.com/inmanturbo "inmanturbo (2 commits)")[![eta-orionis](https://avatars.githubusercontent.com/u/3466670?v=4)](https://github.com/eta-orionis "eta-orionis (1 commits)")[![kayw-geek](https://avatars.githubusercontent.com/u/29700073?v=4)](https://github.com/kayw-geek "kayw-geek (1 commits)")[![Machecek](https://avatars.githubusercontent.com/u/3853689?v=4)](https://github.com/Machecek "Machecek (1 commits)")[![mallardduck](https://avatars.githubusercontent.com/u/619938?v=4)](https://github.com/mallardduck "mallardduck (1 commits)")[![nunomaduro](https://avatars.githubusercontent.com/u/5457236?v=4)](https://github.com/nunomaduro "nunomaduro (1 commits)")[![poldixd](https://avatars.githubusercontent.com/u/695449?v=4)](https://github.com/poldixd "poldixd (1 commits)")[![pxpm](https://avatars.githubusercontent.com/u/7188159?v=4)](https://github.com/pxpm "pxpm (1 commits)")[![randy-allen](https://avatars.githubusercontent.com/u/35460788?v=4)](https://github.com/randy-allen "randy-allen (1 commits)")[![Robertbaelde](https://avatars.githubusercontent.com/u/4356288?v=4)](https://github.com/Robertbaelde "Robertbaelde (1 commits)")[![sawirricardo](https://avatars.githubusercontent.com/u/37329575?v=4)](https://github.com/sawirricardo "sawirricardo (1 commits)")[![stefanzweifel](https://avatars.githubusercontent.com/u/1080923?v=4)](https://github.com/stefanzweifel "stefanzweifel (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/calebporzio-sushi/health.svg)

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

###  Alternatives

[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[clickbar/laravel-magellan

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

423715.4k1](/packages/clickbar-laravel-magellan)[genealabs/laravel-pivot-events

This package introduces new eloquent events for sync(), attach(), detach() or updateExistingPivot() methods on BelongsToMany relation.

1404.9M8](/packages/genealabs-laravel-pivot-events)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[aglipanci/laravel-eloquent-case

Adds CASE statement support to Laravel Query Builder.

115157.2k](/packages/aglipanci-laravel-eloquent-case)

PHPackages © 2026

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