我们在用
Laravel
开发项目时常会用到软删除的功能,此篇文章将用Yii来实现相同的功能。
实现方式是基于Yii特性Behavior
来实现,首先建立一个SoftDeleteBehavior
的行为,如下:
<?php
/**
* IB - SoftDelete - do as Laravel
* User: Great Nomandia
* Date: 2018/12/3 23:38
*/
class SoftDeleteBehavior extends CActiveRecordBehavior
{
/**
* @var string 删除时间字段
*/
public $deletedAttribute = 'deleted_at';
/**
* @var string 删除状态字段
*/
public $deletedStateAttribute = 'state';
/**
* @var int 删除状态值
*/
public $deletedStateValue = 9;
/**
* @var string
*/
public $timestampExpression;
/**
* @var array 映射数据库(MySQL)字段类型对应的默认值
*/
protected static $map = array(
'datetime' => 'NOW()',
'timestamp' => 'NOW()',
'date' => 'NOW()',
'int' => 'UNIX_TIMESTAMP()',
);
/**
* @param CEvent $event
* @return bool
* @throws CException
* Author Nomandia
* Created At 2018/12/3 23:48
*/
function beforeDelete($event)
{
if ($this->getOwner()) {
if (null !== $this->deletedAttribute ) {
// 这里设置删除时间字段
$this->getOwner()->{$this->deletedAttribute} = $this->getTimestampByAttribute($this->deletedAttribute);
}
if (null !== $this->deletedStateAttribute ) {
$this->getOwner()->{$this->deletedStateAttribute} = $this->deletedStateValue;
}
$this->getOwner()->update([$this->deletedStateAttribute, $this->deletedAttribute]);
$event->isValid = false; // 注意这需要设置false以阻止删除行为执行,true则表示实际删除
return false;
}
}
/**
* 获取删除字段对应的列默认值
*
* @param string $attribute $attribute
* @return mixed timestamp (eg unix timestamp or a mysql function)
*/
protected function getTimestampByAttribute($attribute)
{
if ($this->timestampExpression instanceof CDbExpression)
return $this->timestampExpression;
elseif ($this->timestampExpression !== null) {
try {
return @eval('return ' . $this->timestampExpression . ';');
} catch (ParseError $e) {
return false;
}
}
$columnType = $this->getOwner()->getTableSchema()->getColumn($attribute)->dbType;
return $this->getTimestampByColumnType($columnType);
}
/**
* 返回列类型
*
* @param string $columnType $columnType
* @return mixed timestamp (eg unix timestamp or a mysql function)
*/
protected function getTimestampByColumnType($columnType)
{
return isset(self::$map[$columnType]) ? new CDbExpression(self::$map[$columnType]) : time();
}
}
使用起来也很简单
class User extends CActiveRecord{
// other codes
function behaviors()
{
return array_merge([
['class' => 'SoftDeleteBehavior', 'deletedStateAttribute' => null], // 关闭了state更新
], parent::behaviors());
}
// other codes
}