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

ActiveLibrary

wilsonseixo/sushi-sources
=========================

A definitely overkill application of Laravel Sushi

161↓50%PHP

Since Oct 23Pushed 6mo ago1 watchersCompare

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

READMEChangelogDependenciesVersions (1)Used By (0)

Sushi Sources
=============

[](#sushi-sources)

An overkill toolkit for your [Sushi](https://github.com/calebporzio/sushi) models.

If you want to not only read rows from, but also write them to a source like another model's JSON property.

> ⚠ The current major version of this package is 0. Be aware of [what it implies](https://semver.org/#spec-item-4).

Install
-------

[](#install)

```
composer require wilsonseixo/sushi-sources:@dev
```

Use
---

[](#use)

Using this package consists of three steps:

1. Add the `SushiWithSource` trait to a model.
2. Add the `$sourceClass` property to the model.
3. Add the `$sourceContext` property to the model.

You're ready to go.

```
use SushiSources\Sources\JsonFileSource;
use SushiSources\Traits\SushiWithSource;

class Content extends Model
{
    use SushiWithSource;

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

    protected string $sourceClass = JsonFileSource::class;
    protected array $sourceContext = [
        'filename'  => './storage/app/contents.json',
    ];
}
```

Now, whenever you create, update and delete model instances, the source will handle the changes.

```
$content = new Content(['name' => 'Sushi']);
$content->save();
```

In this case, the `json` file will be updated accordingly.

```
[
    {
        "id": 1,
        "name": "Awesome"
    }
]
```

It supports `SoftDeletes`.

Trait options
-------------

[](#trait-options)

You can add some properties to the model to achieve some behaviours:

PropertyBehaviour`bool $stripPrimaryKeys`Strips primary keys from the rows before persisting to the source.Sources
-------

[](#sources)

### Options

[](#options)

Each Sushi model might have its own requirements. For this reason, you can declare properties on the model to change its behavior.

*insert a model class code snippet here*

Below is a list of the properties you can set to change the sources' behavior for the given model.

PropertyBehaviour`array $sourceContext`The context to be passed to the sources' constructor.`bool $persistSushiChanges`Whether to `persist` table changes to the source.`bool $lockDuringSushiPersist`Whether to use the source `lock` while performing changes.`bool $refreshRowsBeforePersist`Whether to `read` rows from the source before persisting changes.`bool $stripPrimaryKeysOnPersist`Whether to strip primary keys from rows when persisting changes.`bool $keyRowsOnPersist`Whether to key rows by primary key when persisting changes.If you need to change the behavior just for the next action, you can use the following methods:

PropertyToggle onToggle off`bool $persistSushiChanges``persistent()``nonPersistent()``bool $lockDuringSushiPersist``locking()``nonLocking()``bool $refreshRowsBeforePersist``rowRefreshing()``nonRowRefreshing()``bool $stripPrimaryKeysOnPersist``keyStripping()``nonKeyStripping()``bool $keyRowsOnPersist``rowKeying()``nonRowKeying()`After an action is performed, the temporary flags are cleared using the method `clearMutatingFlags()`.

### Default sources

[](#default-sources)

The package comes with some default sources.

#### `Source` abstract

[](#source-abstract)

The `Source` abstract class is what you should use to implement your own source.

Context options:

PropertyTypeDescription`refresh_on_read``bool`Whether the source should be refreshed when `read` is called. (*pending implementation*)`refresh_on_write``bool`Whether the source should be refreshed when `write` is called. (*pending implementation*)`refresh_on_persist``bool`Whether the source should be refreshed when `persist` is called. (*pending implementation*)#### `JsonFileSource`

[](#jsonfilesource)

The `JsonFileSource` reads from and writes to a `.json` file.

```
$sourceClass = JsonFileSource::class;
$sourceContext = [
    'filename'  => './storage/app/contents.json',
];
```

Context options:

PropertyTypeDescription`filename``string`The file path to be used as the source.`json_depth``int``$depth` argument for `json_decode` and `json_encode``json_decode_flags``int``$flags` argument for `json_decode``json_encode_flags``int``$flags` argument for `json_encode`#### `ModelSource`

[](#modelsource)

The `ModelSource` reads from and writes to a model instance property.

```
class Section extends Model
{
    use SushiWithSource;

    protected $schema = [
        'id' => 'integer',
        'value' => 'string'
    ];

    protected string $sourceClass = ModelSource::class;
    protected array $sourceContext = [
        'class'     => Content::class,
        'property'  => 'sections',
    ];
}
```

You might know the instance primary key beforehand and specify it in the source context. But you can also assign an instance dynamically:

```
$content = new Content(['name' => 'Sushi']);
Section::setSushiContext('model', $content);
```

Context options:

PropertyTypeDescription`class``string`The model class.`key``mixed`The model instance key the source should fetch using `Model::find()`.`query``array`Alternatively to the key, you can specify Eloquent builder methods to perform the query.
 The key is the method and the value is the respective array of arguments (i.e., `['where', ['code', 'something']]`).`model``Model`The model instance being used as the source.Notes
-----

[](#notes)

### Mass actions

[](#mass-actions)

Changes on the sources are triggered by Eloquent events, which means that mass-inserting, updating and deleting will not trigger the `persist()` method on the source.

To solve this problem, you must call static method `persistSushiBulk()` (*pending implementation*) on the model to force

```
Section::insert([
    ['value' => 'Heading'],
    ['value' => 'Paragraph'],
]);
Section::persistSushiBulk();
```

Roadmap
-------

[](#roadmap)

- Documentation
    - Improve `README.md`
    - Create `EXAMPLES.md`?
- Trait
    - Static method `persistSushiBulk()`
- Sources
    - `refresh` flags functionality
        - `refresh_on_read`
        - `refresh_on_write`
        - `refresh_on_persist`
- Examples
- Tests

**Sushi Sources** was created by **[Wilson Ferreira](https://twitter.com/wilsonseixo)** under the **[MIT license](https://opensource.org/licenses/MIT)**.

###  Health Score

19

—

LowBetter than 10% of packages

Maintenance46

Moderate activity, may be stable

Popularity10

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity13

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/57537bb89e85a4480309f457a4287172fd0a4d9c4068138a89023a2b994a4fe4?d=identicon)[wilsonseixo](/maintainers/wilsonseixo)

---

Top Contributors

[![wilsonseixo](https://avatars.githubusercontent.com/u/64915558?v=4)](https://github.com/wilsonseixo "wilsonseixo (9 commits)")

### Embed Badge

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

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

PHPackages © 2026

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