Sushi Documentation

repository·main·Indexed 25 days ago

https://github.com/calebporzio/sushi

An Eloquent "array" driver that allows the use of Eloquent models with static or dynamic array data without a traditional database by creating and caching a local SQLite database for the model.

Tokens
2K
Snippets
11
Records
11
Agent score
34%

What's inside Sushi

  1. Use Sushi models in Laravel validation rules

    main

    You can use the exists:table,column validation rule with Sushi models. You must use the fully-qualified namespace of the model instead of a table name to ensure Laravel resolves the correct connection.

    $data = request()->validate([
        'state' => ['required', 'exists:App\Models\State,abbr'],
    ]);
  2. Handle empty datasets in Sushi

    main

    Sushi determines the table schema by reading the first row of the dataset. If getRows() returns an empty array, Sushi will throw an error. To support empty datasets, you must explicitly define the schema using the protected $schema property.

    class Currency extends Model
    {
        use \Sushi\Sushi;
    
        protected $schema = [
            'id' => 'integer',
            'name' => 'string',
            'symbol' => 'string',
            'precision' => 'float'
        ];
    
        public function getRows()
        {
            return [];
        }
    }
  3. Basic usage of Sushi models

    main

    To use Sushi, add the \Sushi\Sushi trait to your Eloquent model and define a $rows property containing your data as an array of associative arrays. The model will then behave like a standard database-backed model.

    class State extends Model
    {
        use \Sushi\Sushi;
    
        protected $rows = [
            [
                'abbr' => 'NY',
                'name' => 'New York',
            ],
            [
                'abbr' => 'CA',
                'name' => 'California',
            ],
        ];
    }
    
    // Usage:
    $stateName = State::whereAbbr('NY')->first()->name;
  4. Define relationships with Sushi models

    main

    You can define standard Eloquent relationships (like belongsTo) between a regular database model and a Sushi model.

    Caveat: The whereHas method will NOT work because the models reside in separate databases.

    class Role extends Model
    {
        use \Sushi\Sushi;
    
        protected $rows = [
            ['id' => 1, 'label' => 'admin'],
            ['id' => 2, 'label' => 'manager'],
            ['id' => 3, 'label' => 'user'],
        ];
    }
    
    class User extends Model
    {
        public function role()
        {
            return $this->belongsTo(Role::class);
        }
    }
    
    // Usage:
    $user = User::first();
    $role = Role::whereLabel('admin')->first();
    $user->role()->associate($role);
    $user->role;
    $user->load('role');
  5. Fix SQLSTATE[HY000]: General error: 1 too many SQL variables

    main

    If you encounter the error SQLSTATE[HY000]: General error: 1 too many SQL variables, it is likely because the default chunk size for SQLite inserts is too high for your environment. You can reduce the chunk size by setting the $sushiInsertChunkSize property on your model.

    class MyModel extends Model
    {
        use \Sushi\Sushi;
    
        public $sushiInsertChunkSize = 50;
    }
  6. Configure string-based primary keys

    main

    If your Sushi model uses a string-based primary key, you must set both $incrementing to false and $keyType to 'string'.

    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'],
        ];
    }
  7. Implement dynamic rows with getRows()

    main

    Instead of a static $rows property, implement getRows() to determine the model's data at runtime (e.g., fetching from an external API).

    Note: When using getRows(), rows are not cached between requests by default.

    class Role extends Model
    {
        use \Sushi\Sushi;
    
        public function getRows()
        {
            return [
                ['id' => 1, 'label' => 'admin'],
                ['id' => 2, 'label' => 'manager'],
                ['id' => 3, 'label' => 'user'],
            ];
        }
    }
  8. Customize Sushi schema

    main

    If Sushi's automatic schema detection is insufficient, you can define the schema using the protected $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',
        ];
    }
  9. Customize table structure with afterMigrate()

    main

    Implement the afterMigrate(Blueprint $table) method to perform custom operations on the SQLite table after it is created, such as adding indexes.

    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');
        }
    }
  10. Enable caching for getRows()

    main

    To cache datasets generated by getRows(), implement sushiShouldCache() and return true.

    You can also use sushiCacheReferencePath() to specify an external file (like a .csv) that Sushi should monitor to determine if the cache needs to be rebuilt.

    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';
        }
    }