fanmade / laravel-bitwise-trait
在任意类上使用位运算符的简单特质
Requires
- php: >=7.4
Requires (Dev)
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2024-08-29 04:25:35 UTC
README
这是一个在任意类上使用位运算符的简单特质,灵感来源于 https://php.ac.cn/manual/de/language.operators.bitwise.php#108679
在阅读了这篇博客后进行了更新: https://aaronfrancis.com/2021/bitmasking-in-laravel-and-mysql
我目前只在Laravel中使用了它,但你应该可以在经过一些小的修改后在任何其他地方使用它。
PHP 版本
版本 v2.* 需要 PHP 7.4+。如果你还使用着旧版本,请使用 v1.*
安装
你可以通过 composer 安装此包
composer require fanmade/laravel-bitwise-trait
这就完了,不需要注册提供者 :)
用法
以下示例是针对默认 Laravel (5.4) 模型中的 "App" 命名空间。
你需要一个(理想情况下无符号)整数字段在数据库中存储属性。长度取决于你想要存储的值的数量。每个值只需要一个比特位,所以如果列是无符号的,每字节可以有8个值。
示例(基于 Laravel 迁移)
$table->tinyInteger('status'); // 1 byte -> maximum of 7 different values $table->unsignedTinyInteger('status'); // maximum of 8 different values $table->smallInteger('status'); // 2 byte -> maximum of 16 different values $table->unsignedSmallInteger('status'); // maximum of 17 different values $table->mediumInteger('status'); // 3 byte -> maximum of 24 different values
你大概明白了。大多数时候你可能只需要一个无符号的小整型 :)
对于多于一个数据库字段的使用场景只有少数几种,但你可以添加你想要的任意数量的字段。
在你的模型中这样包含特质
<?php namespace App; use Fanmade\Bitwise\BitwiseFlagTrait; class Message extends Model { use BitwiseFlagTrait;
定义属性的最佳方式是直接在模型中通过常量。当然,你也可以自由使用配置变量或任何你喜欢的。
const MESSAGE_SENT = 1; // BIT #1 of has the value 1 const MESSAGE_RECEIVED = 2; // BIT #2 of has the value 2 const MESSAGE_SEEN = 4; // BIT #3 of has the value 4 const MESSAGE_READ = 8; // BIT #4 of has the value 8
这种替代语法可能更容易阅读
const MESSAGE_SENT = 1 << 0; const MESSAGE_RECEIVED = 1 << 1; const MESSAGE_SEEN = 1 << 2; const MESSAGE_READ = 1 << 3;
或者直接使用二进制表示
const MESSAGE_SENT = 0b00000001; const MESSAGE_RECEIVED = 0b00000010; const MESSAGE_SEEN = 0b00000100; const MESSAGE_READ = 0b00001000;
要设置属性,只需像这样调用函数
$this->setFlag('status', self::MESSAGE_SENT, true);
要获取属性,只需像这样调用函数
$sent = $this->getFlag('status', self::MESSAGE_SENT);
第一个参数 ('status' 在示例中) 总是你在数据库中设置的列。也许你想要在常量或变量中定义它。
为了使你的生活更简单,我建议使用自定义的获取器和设置器。
public function setSentAttribute($sent = true): self { $this->setFlag('status', self::MESSAGE_SENT, $sent); return $this; } public function getSentAttribute(): bool { return $this->getFlag('status', self::MESSAGE_SENT); }
作用域
如果你想在使用作用域时使用新字段,可以这样做
/** * @param Builder $query * @return Builder */ public function scopeUnread($query) { return $query->whereRAW('NOT status & ' . self::MESSAGE_READ); } /** * @param Builder $query * @return Builder */ public function scopeRead($query) { return $query->where('status', '&', self::MESSAGE_READ); }