1

我在我的表中使用 UUID 作为 PK。它们存储在BINARY(16)MySQL 列中。我发现它们被映射为string输入 YII。不过,我生成的 CRUD 代码会发生故障,因为这些二进制列类型是在视图中进行 HTML 编码的。例子:

<?php echo 
        CHtml::link(CHtml::encode($data->usr_uuid), /* This is my binary uuid field */
        array('view', 'id'=>$data->usr_uuid)); ?>

为了解决这个问题,我afterFind()beforeSave()我的模型中分别使用bin2hexand将值转换为/从十六进制转换hex2bin。有关更多详细信息,请参阅内容。

这可以解决视图问题。

但是,现在在访问表单的 url 时搜索 PK:

http://myhost.com/mysite/user/ec12ef8ebf90460487abd77b3f534404

导致User::loadModel($id)被调用,而后者又调用:

User::model()->findByPk($id);

这不起作用,因为正在生成 SQL(因为它被映射到 phpstring类型)是

select ... where usr_uuid='EC12EF8EBF90460487ABD77B3F534404'

如果可以的话,会发生什么,因为这些 uuid 字段将条件更改为:

select ... where usr_uuid=unhex('EC12EF8EBF90460487ABD77B3F534404')

我想知道我如何干净地处理这个问题。我看到了一种可能性 - 扩展CMysqlColumnSchema和覆盖特殊情况的必要方法并将 binary(16) 列作为 uuid 类型处理。

这看起来并不整洁,因为uuid在 php(它被视为字符串)或 mysql(我将它作为 binary(16) 列)中不支持本机。

有人有什么建议吗?

4

2 回答 2

1

如果您打算在自己的代码中使用它,那么我将创建自己的基础 AR 类:

class ActiveRecord extends CActiveRecord
{
  // ...
  public function findByUUID($uuid)
  {
    return $this->find('usr_uuid=unhex(:uuid)', array('uuid' => $uuid));
  }
}

如果是关于使用生成的代码等,那么稍微自定义模式可能是个好主意。

于 2013-10-31T09:16:33.967 回答
0

我使用以下方法使使用 Yii/MySQL 处理 uuid (binary(16)) 列成为可能且高效。我提到了高效,因为我可以只用破折号将列设为 CHAR(32) 或 (36),但这确实会使效率高出窗外。

我对其进行了扩展CActiveRecord并添加了一个虚拟属性uuid。还重载了两个基类方法getPrimaryKeysetPrimaryKey. 有了这些变化,大部分 Yii 都很高兴。

class UUIDActiveRecord extends CActiveRecord 
{
    public function getUuid()
    {
        $pkColumn = $this->primaryKeyColumn;
        return UUIDUtils::bin2hex($this->$pkColumn);
    }

    public function setUuid($value)    
    {
        $pkColumn = $this->primaryKeyColumn;
        $this->$pkColumn = UUIDUtils::hex2bin($value);
    }

    public function getPrimaryKey()
    {
            return $this->uuid;
    }

    public function setPrimaryKey($value)        
    {
            $this->uuid = $value;
    }

    abstract public function getPrimaryKeyColumn();
}

现在我使用这个虚拟属性获取/设置 UUID:

$model->uuid = generateUUID();  // return UUID as 32 char string without the dashes (-)

最后一点,关于我如何搜索。这是使用以下方法完成的:

$criteria = new CDbCriteria();
$criteria->addCondition('bkt_user = unhex(:value)');
$criteria->params = array(':value'=>Yii::app()->user->getId()); //Yii::app()->user->getId() returns id as hex string
$buckets = Bucket::model()->findAll($criteria);

最后一点,参数记录,即以下行main.php

'db'=>array(
    ...
    'enableParamLogging' => true,
    );

仍然不起作用,因为 Yii 将再次尝试对二进制数据进行 html 编码(不是一个好主意)。我还没有找到解决方法,所以我在我的配置文件中禁用了它。

于 2013-10-31T11:04:33.147 回答