在yii中处理uuid pk列

时间:2013-10-20 17:35:16

标签: yii

我在桌子上使用UUID作为PK。它们存储在BINARY(16) MySQL列中。我发现他们在YII中被映射到string类型。我生成的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(),我分别使用bin2hexhex2bin将值转换为/从十六进制转换。有关详细信息,请参阅this

这可以解决视图问题。

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

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

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

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

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

select ... where usr_uuid='EC12EF8EBF90460487ABD77B3F534404'

如果可以,那会有效,因为这些uuid字段会将条件更改为:

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

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

这似乎并不整洁,因为在php(它被视为字符串)或mysql(我将其作为二进制(16)列)中原生地支持uuid

有人有任何建议吗?

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

我使用以下方法使用Yii / MySQL的uuid(二进制(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编码二进制数据(不是一个好主意)。我还没有找到解决方法,所以我在配置文件中禁用了它。