Yii2处理二进制数据方法:创建ActiveRecord及带UNHEX的查询
Yii框架下二进制字段表的ActiveRecord实现与查询方案
1. 创建对应表的基础ActiveRecord模型
首先在模型目录下创建对应digiid_callback表的模型类,基础写法如下:
namespace app\models; use yii\db\ActiveRecord; class DigiidCallback extends ActiveRecord { // 绑定对应的数据表名 public static function tableName() { return 'digiid_callback'; } }
这个基础模型可以直接完成基础CRUD,但因为表中存在BINARY类型的二进制字段,直接读写会出现乱码、查询匹配失败的问题,需要额外做字段值的转换处理。
2. 配置二进制字段的自动转换逻辑
通过模型内置的生命周期钩子,可以实现二进制数据和可读十六进制字符串的自动转换,业务层不需要每次手动调用HEX/UNHEX函数:
namespace app\models; use yii\db\ActiveRecord; class DigiidCallback extends ActiveRecord { public static function tableName() { return 'digiid_callback'; } // 数据从库中读取完成后,自动把二进制字段转为十六进制字符串 public function afterFind() { parent::afterFind(); if ($this->nonce !== null) { $this->nonce = bin2hex($this->nonce); } if ($this->address !== null) { $this->address = bin2hex($this->address); } } // 数据写入数据库前,自动把十六进制字符串转回二进制格式 public function beforeSave($insert) { if (!parent::beforeSave($insert)) { return false; } if ($this->nonce !== null) { $this->nonce = hex2bin($this->nonce); } if ($this->address !== null) { $this->address = hex2bin($this->address); } return true; } }
配置完成后,业务代码中读写nonce、address字段都直接用十六进制字符串即可,不需要关心底层的二进制存储逻辑。
3. 实现带UNHEX函数的二进制条件查询
如果没有做上面的全局自动转换,或者需要直接用十六进制格式的nonce值查询,不能直接调用findOne()传参——默认的查询逻辑会把传入值当普通字符串做等值匹配,无法命中二进制存储的字段值,需要用数据库表达式明确调用UNHEX函数:
// 传入的$nonceHex为十六进制格式的nonce值 $nonceHex = 'a1b2c3d4e5f67890'; $record = DigiidCallback::find() ->where(['nonce' => new \yii\db\Expression('UNHEX(:nonce)', [':nonce' => $nonceHex])]) ->one();
如果这类查询使用频率高,可以直接在模型中封装静态查询方法简化调用:
public static function findByNonce(string $nonceHex) { return static::find() ->where(['nonce' => new \yii\db\Expression('UNHEX(:nonce)', [':nonce' => $nonceHex])]) ->one(); }
后续业务中直接调用DigiidCallback::findByNonce('你的十六进制nonce值')即可拿到对应记录。
注意事项
expire字段是TIMESTAMP类型,Yii会自动识别为时间格式,不需要额外做类型转换,可直接配合框架的自动时间戳功能使用address字段允许为NULL,做二进制/十六进制转换前必须判空,否则会触发PHP类型警告- 禁止直接把十六进制字符串传入
findOne()作为nonce的查询条件,否则会因为类型不匹配返回空结果
内容的提问来源于stack exchange,提问作者Matthew Cornelisse
相关产品推荐
相关产品推荐

