macropage / sushi
Eloquent 缺失的 "array" 驱动器。
资助包维护!
calebporzio
Requires
- php: ^7.1.3|^8.0
- illuminate/database: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0
- illuminate/support: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0
Requires (Dev)
- doctrine/dbal: ^2.9 || ^3.1.4
- orchestra/testbench: 3.8.* || 3.9.* || ^4.0 || ^6.0 || ^7.0 || ^8.0
- phpunit/phpunit: ^7.5 || ^8.4 || ^9.0
This package is auto-updated.
Last update: 2024-09-06 06:40:32 UTC
README
我不明白这对有原始代码的人来说是如何工作的。
有了这个更改,我可以从任何 mysql-query 中创建模型。
$QueryResult = new QueryResultModel(); // $connection_name from config/database.php $QueryResult->initbootSushi($connection_name, $sql_query_string);
<?php namespace App\Models; use DB; use Illuminate\Database\Eloquent\Model; use Sushi\Sushi; class QueryResult extends Model { use Sushi; private ?string $use_connection = NULL; private ?string $use_query = NULL; public function getRows(): array { $result = DB::connection($this->use_connection)->select($this->use_query); return array_map(fn($x) => (array)$x, $result); } /** * @param mixed $use_query */ public function setUseQuery(string $use_query): void { $this->use_query = $use_query; } /** * @param mixed $use_connection */ public function setUseConnection(string $use_connection): void { $this->use_connection = $use_connection; } }
Sushi 🍣
Eloquent 缺失的 "array" 驱动器。
有时你想使用 Eloquent,但又不想处理数据库。
此包是赞助软件 💰💰💰
最初,此包仅在 GitHub Sponsors 的赞助者中可用,直到我达到 75 位赞助者。
现在我们已经达到目标,该包现在是完全开源的。
享受,并感谢支持! ❤️
在 github.com/sponsorware/docs 上了解更多关于 赞助软件 的信息 💰。
安装
composer require calebporzio/sushi
使用
使用此包包括两个步骤
- 将
Sushi特性添加到模型中。 - 将
$rows属性添加到模型中。
就这样。
class State extends Model { use \Sushi\Sushi; protected $rows = [ [ 'abbr' => 'NY', 'name' => 'New York', ], [ 'abbr' => 'CA', 'name' => 'California', ], ]; }
现在,您可以在任何地方使用此模型,它将表现得像您创建了包含您提供的行的表一样。
$stateName = State::whereAbbr('NY')->first()->name;
这对于 "Fixture" 数据(如国家、地区、邮编、用户角色、站点设置等)非常有用。
关系
假设您创建了一个基于数组使用 Sushi 的 Role 模型,如下所示
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); } }
假设 users 表有一个 role_id 列,您可以这样做
// 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();
注意:处理 Sushi 模型关系时有一个注意事项。
whereHas方法将不会工作。这是因为两个模型分布在两个不同的数据库中。
使用数据库检查验证规则
您甚至可以使用 Laravel 的 exists:table,column 数据库检查请求验证规则。
$data = request()->validate([ 'state' => ['required', 'exists:App\Model\State,abbr'], ]);
注意:请注意,您必须使用模型的完全限定命名空间而不是表名。这确保 Laravel 正确解析模型的连接。
自定义模式
如果 Sushi 的模式自动检测系统不能满足您对提供的行数据的特定要求,您可以使用 $schema 属性或 getSchema() 方法来自定义它们。
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', ]; }
工作原理
在底层,此包为该模型创建并缓存了一个 SQLite 数据库。它创建一个表并填充行。如果由于任何原因无法缓存 .sqlite 文件,它将默认使用内存中的 sqlite 数据库。
使用 ->getRows()
您可以选择不使用 protected $rows 属性,并直接实现自己的 getRows() 方法。
这将允许您在运行时确定模型的行。您甚至可以从第三方 API 等外部源生成模型的行。
class Role extends Model { use \Sushi\Sushi; public function getRows() { return [ ['id' => 1, 'label' => 'admin'], ['id' => 2, 'label' => 'manager'], ['id' => 3, 'label' => 'user'], ]; } }
缓存 ->getRows()
如果您选择使用自己的 ->getRows() 方法,则默认情况下不会在请求之间缓存行。
您可以使用以下方法强制 Sushi 缓存您的数据集:sushiShouldCache()。
以下是一个示例配置,其中 ->getRows() 数据集将被缓存
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; } }
默认情况下,Sushi会查看您的模型PHP文件的“最后修改”时间戳,并将其与内部的.sqlite缓存文件进行比较。如果模型文件比.sqlite缓存文件更早被修改,那么Sushi将销毁并重建.sqlite缓存。此外,您还可以配置一个外部文件,让Sushi在确定缓存是否是最新的或需要刷新时参考。
例如,如果您使用Sushi为外部数据源文件(如.csv文件)提供一个Eloquent模型,您可以使用sushiCacheReferencePath强制Sushi在确定缓存是否过时时参考.csv文件。
例如
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'; } }
现在,只有当roles.csv发生变化时,Sushi才会“破坏”其内部缓存,而不是查看Role.php模型。
处理空数据集
Sushi会读取数据集的第一行以确定SQLite表的方案。如果您使用getRows()并且这返回一个空数组(例如API没有返回任何内容),那么Sushi会抛出错误。
如果您希望即使数据集为空,Sushi也能正常工作,您可以在可选的protected $schema数组中定义您的方案。
注意:如果您选择使用自己的
->getRows()方法,则请求之间不会缓存行。
class Currency extends Model { use \Sushi\Sushi; protected $schema = [ 'id' => 'integer', 'name' => 'string', 'symbol' => 'string', 'precision' => 'float' ]; public function getRows() { return []; } }
处理基于字符串的主键
如果模型使用基于字符串的主键,Sushi要求您在模型中添加两个属性:$incrementing和$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'], ]; }
故障排除
错误: SQLSTATE[HY000]: General error: 1 too many SQL variables
默认情况下,Sushi使用100个数据块来将数据插入SQLite数据库。在某些情况下,这可能会触及SQLite的限制。您可以在模型中配置数据块大小:public $sushiInsertChunkSize = 50;