Eloquent 缺失的 "array" 驱动器。

维护者

详细信息

github.com/calebporzio/sushi

源代码

资助包维护!
calebporzio

安装次数: 3,558,474

依赖关系: 100

建议者: 0

安全: 0

星星: 2,558

关注者: 42

分支: 167

v2.5.2 2024-04-24 15:23 UTC

README

Eloquent 缺失的 "array" 驱动器。

有时你想使用 Eloquent,但又不想处理数据库。

此包是赞助软件 💰💰💰

最初,这个包仅对我的 GitHub Sponsors 上的赞助者可用,直到我达到了 75 个赞助者。

现在我们已经达到目标,这个包是完全开源的。

享受吧,感谢您的支持! ❤️

github.com/sponsorware/docs 了解更多关于 赞助软件 的信息 💰。

需求

您必须安装系统上的 pdo-sqlite PHP 扩展 才能使用此包。

安装

composer require calebporzio/sushi

使用

使用此包包括两个步骤

  1. Sushi 特性添加到模型中。
  2. 向模型添加一个 $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;

这对于“固定”数据非常有用,如州、国家、邮编、用户角色、站点设置等...

关系

假设您创建了一个 Role 模型,使用 Sushi 通过数组创建,如下所示

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\Models\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',
    ];
}

高级用法

当您需要更多灵活性时,您可以实现 afterMigrate(BluePrint $table) 方法,允许您在表创建后自定义它。这可能对向某些列添加索引很有用。

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

工作原理

在内部,此包只为该模型创建并缓存一个 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'],
        ];
    }
}

Caching ->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;