目录树 / activeredis
Redis的ActiveRecord实现。
Requires
- php: >=8.1
- illuminate/contracts: ^9.0|^10.0|^11.0
- illuminate/support: ^9.0|^10.0|^11.0
- predis/predis: ^2.0
Requires (Dev)
- laravel/pint: ^1.17
- orchestra/testbench: ^7.0|^8.0|^9.0
- pestphp/pest: ^1.0|^2.0|^3.0
This package is auto-updated.
Last update: 2024-09-23 14:37:50 UTC
README
使用散列在Laravel中为Redis实现Active Record。
ActiveRedis使用Redis散列来存储和检索模型数据,为Laravel中与Redis的交互提供了一种简单高效的方式。
索引
需求
- PHP >= 8.1
- Predis >= 2.0
- Laravel >= 9.0
安装
您可以通过composer安装此包
composer require directorytree/activeredis
使用
创建模型
要开始使用,定义一个新的ActiveRedis模型
namespace App\Redis; use DirectoryTree\ActiveRedis\Model; class Visit extends Model {}
然后,创建具有所需数据的模型
重要
分配给模型属性的值始终以字符串的形式存储在Redis中。
use App\Redis\Visit; $visit = Visit::create([ 'ip' => request()->ip(), 'url' => request()->url(), 'user_agent' => request()->userAgent(), ]);
这将创建一个新的Redis散列,其格式如下
{plural_model_name}:{key_attribute}:{key_value}
例如
visits:id:f195637b-7d48-43ab-abab-86e93dfc9410
按照您在模型实例上预期的方式访问属性
重要
属性值始终以字符串的形式存储在Redis中。如果您想保留值的类型,请使用模型转换。
$visit->ip; // xxx.xxx.xxx.xxx $visit->url; // https://example.com $visit->user_agent; // Mozilla/5.0 ...
模型标识符
在创建模型时,ActiveRedis将为每个模型自动生成一个UUID,分配给id
属性
$visit->id; // "f195637b-7d48-43ab-abab-86e93dfc9410" $visit->getKey(); // "f195637b-7d48-43ab-abab-86e93dfc9410" $visit->getHashKey(); // "visits:id:f195637b-7d48-43ab-abab-86e93dfc9410" $visit->getKeyName(); // "id" $visit->getBaseHash(); // "visits:id" $visit->getHashPrefix(): // "visits"
如果您愿意,也可以提供自己的ID
$visit = Visit::create([ 'id' => 'custom-id', // ... ]); $visit->id; // "custom-id" $visit->getHashKey(); // "visits:id:custom-id"
尝试创建具有现有ID的模型将导致DuplicateKeyException
异常
Visit::create(['id' => 'custom-id']); // DuplicateKeyException: A model with the key 'custom-id' already exists. Visit::create(['id' => 'custom-id']);
同样,尝试创建具有空ID的模型将抛出InvalidKeyException
异常
// InvalidKeyException: A key is required to create a model. Visit::create(['id' => '']);
要更改存储模型键的字段名称,可以重写key
属性
namespace App\Redis; use DirectoryTree\ActiveRedis\Model; class Visit extends Model { protected string $key = 'custom_key'; }
如果您不提供,ActiveRedis将始终在键的属性中生成一个新的UUID。
要更改此行为或生成自己的唯一键,可以重写getNewKey()
方法
重要
不要使用冒号(:)或星号(*)生成键。它们是Redis中的保留字符。
这也适用于定义为可查询的属性。
namespace App\Redis; use Illuminate\Support\Str; use DirectoryTree\ActiveRedis\Model; class Visit extends Model { // ... protected function getNewKey(): string { return Str::orderedUuid(); } }
模型时间戳
模型还将维护created_at
和updated_at
属性
重要
当访问时,时间戳属性将以Carbon
实例的形式返回。
$visit->created_at; // \Carbon\Carbon('2024-01-01 00:00:00') $visit->updated_at; // \Carbon\Carbon('2024-01-01 00:00:00')
要仅更新模型的updated_at
时间戳,可以调用touch()
方法
$visit->touch();
您还可以提供要触摸的时间戳属性
$visit->touch('created_at');
要禁用时间戳,可以重写timestamps
属性并将其设置为false
class Visit extends Model { /** * Indicates if the model should be timestamped. */ public bool $timestamps = false; }
如果您需要自定义用于存储时间戳的列的名称,可以在模型上定义CREATED_AT
和UPDATED_AT
常量
class Visit extends Model { const CREATED_AT = 'creation_date'; const UPDATED_AT = 'updated_date'; }
模型转换
要将模型属性转换为特定类型,可以在模型上定义casts
属性
class Metric extends Model { protected array $casts = [ 'user_id' => 'integer', 'authenticated' => 'boolean', ]; }
当您访问属性时,它将转换为指定的类型
$metric = new Metric([ 'user_id' => '1', 'authenticated' => '1', ]); $metric->user_id; // (int) 1 $metric->authenticated; // (bool) true $metric->getAttributes(); // ['user_id' => '1', 'authenticated' => '1'],
以下是所有支持的转换列表
json
date
array
string
object
decimal
timestamp
collection
int|integer
bool|boolean
real|float|double
datetime|custom_datetime
immutable_date|immutable_custom_datetime|immutable_datetime
还有可用的枚举转换
use App\Enums\MetricCategory; class Metric extends Model { protected array $casts = [ 'category' => MetricCategory::class, ]; }
更新模型
您可以使用update()
方法更新模型
$visit->update([ 'ip' => 'xxx.xxx.xxx.xxx', 'url' => 'https://example.com', 'user_agent' => 'Mozilla/5.0 ...', ]);
或者通过设置模型属性并调用save()
方法
$visit->ip = 'xxx.xxx.xxx.xxx'; $visit->save();
删除模型
要删除模型,请在模型实例上使用delete()
方法
$visit->delete();
或者,您也可以通过它们的ID来删除模型
$deleted = Visit::destroy('f195637b-7d48-43ab-abab-86e93dfc9410'); echo $deleted; // 1
您可以通过提供ID数组来删除多个模型
$deleted = Visit::destroy(['f195637b...', 'a195637b...']); echo $deleted; // 2
过期模型
要使模型在一段时间后过期,请使用setExpiry()
方法
$visit->setExpiry(now()->addMinutes(5));
5分钟后,该模型将自动从Redis中删除。
查询模型
查询模型使用Redis的SCAN
命令来遍历模型哈希集中的所有键。
例如,当查询Visit模型时,使用模式visits:id:*
SCAN {cursor} MATCH visits:id:* COUNT {count}
要开始查询模型,您可以在模型上调用query()
方法
$visits = Visit::query()->get();
这将遍历模型哈希集中的所有键,并返回匹配该模式的模型集合。
缺少的模型方法将被转发到查询构建器,因此如果您喜欢,可以在模型上动态调用查询方法。
$visits = Visit::get();
分块
您可以使用chunk()
方法分块查询结果
Visit::chunk(100, function ($visits) { $visits->each(function ($visit) { // ... }); });
或调用each
方法
Visit::each(100, function ($visit) { // ... });
在回调中返回false
可以停止分块查询
Visit::each(function ($visit) { if ($visit->ip === 'xxx.xxx.xxx.xxx') { return false; } });
过滤
在尝试过滤模型之前,您必须定义您想要在模型上查询的属性
class Visit extends Model { protected array $queryable = ['ip']; }
当您定义这些属性时,它们将以以下格式作为哈希键的一部分进行存储
visits:id:{id}:ip:{ip}
例如
visits:id:f195637b-7d48-43ab-abab-86e93dfc9410:ip:127.0.0.1
当定义多个可查询属性时,它们将按字母顺序存储。例如
class Metric extends Model { protected array $queryable = ['user_id', 'company_id']; } // ... $metric = Metric::create([ 'user_id' => 1, 'company_id' => 1, ]); $metric->getHashKey(); // "metrics:id:{uuid}:company_id:1:user_id:1"
一旦定义了可查询属性,您就可以使用where()
方法开始查询它们
// SCAN ... MATCH visits:id:*:ip:127.0.0.1 $visit = Visit::where('ip', '127.0.0.1')->first();
您还可以在where子句中使用通配符进行通配搜索
// SCAN ... MATCH visits:id:*:ip:127.0.* $visit = Visit::where('ip', '127.0.*')->first();
检索模型
要检索模型,请使用find
方法
$visit = Visit::find('f195637b-7d48-43ab-abab-86e93dfc9410');
如果您希望在找不到模型时抛出异常,请使用findOrFail
方法
Visit::findOrFail('missing'); // ModelNotFoundException