Install Sushi via Composer
mainInstall the Sushi package using Composer to add the Eloquent "array" driver to your project.
composer require calebporzio/sushirepository·main·Indexed 25 days ago
https://github.com/calebporzio/sushiAn 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.
Install the Sushi package using Composer to add the Eloquent "array" driver to your project.
composer require calebporzio/sushiYou 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'],
]);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 [];
}
}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;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');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;
}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'],
];
}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'],
];
}
}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',
];
}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');
}
}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';
}
}