帮酷LOGO
  • 显示原文与译文双语对照的内容
Soft delete behavior for ActiveRecord

  • 源代码名称:ar-softdelete
  • 源代码网址:http://www.github.com/yii2tech/ar-softdelete
  • ar-softdelete源代码文档
  • ar-softdelete源代码下载
  • Git URL:
    git://www.github.com/yii2tech/ar-softdelete.git
  • Git Clone代码到本地:
    git clone http://www.github.com/yii2tech/ar-softdelete
  • Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/yii2tech/ar-softdelete
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
  • 用于Yii2的ActiveRecord软删除扩展

    这里扩展为ActiveRecord软删除提供支持。

    许可证信息检查许可证 -file"。

    Latest Stable VersionTotal DownloadsBuild Status

    安装

    安装这个扩展的首选方法是通过 composer插件。

    运行

    php composer.phar require --prefer-dist yii2tech/ar-softdelete

    或者添加

    "yii2tech/ar-softdelete": "*"

    到 composer.json.的要求部分

    用法

    这个扩展提供了"柔和"删除的支持,这意味着记录不会从数据库中删除,而标记为,。

    这里扩展提供了 [[yii2techarsoftdeleteSoftDeleteBehavior] ] ActiveRecord在Yii2中支持这种解决方案的行为。 你可以按以下方式将它附加到模型类:

    classItemextendsActiveRecord{publicfunctionbehaviors() {return ['softDeleteBehavior'=> ['class'=>SoftDeleteBehavior::className(),'softDeleteAttributeValues'=> ['isDeleted'=>true ], ], ]; }}

    "柔和"删除应用的方法有 2种:

    • 使用 softDelete() 分离方法
    • 改变常规 delete() 方法

    建议使用 softDelete(),因为它允许将记录标记为"已经删除",同时保留正常的delete() 方法,如果需要则执行"硬硬盘"删除。 例如:

    $id=17;$item=Item::findOne($id);$item->softDelete(); // mark record as"deleted"$item=Item::findOne($id);var_dump($item->isDeleted); // outputs"true"$item->delete(); // perform actual deleting of the record$item=Item::findOne($id);var_dump($item); // outputs"null"

    但是,你可能希望在执行"柔和"删除的方法中改变常规的ActiveRecord delete() 方法,而不是实际删除记录。 在这种情况下,对于现有代码应用"柔和"删除功能是一种常见的解决方案。 对于此类功能,你应该在行为配置中启用 [[yii2techarsoftdeleteSoftDeleteBehavior::$replaceRegularDelete] ] 选项:

    classItemextendsActiveRecord{publicfunctionbehaviors() {return ['softDeleteBehavior'=> ['class'=>SoftDeleteBehavior::className(),'softDeleteAttributeValues'=> ['isDeleted'=>true ],'replaceRegularDelete'=>true// mutate native `delete()` method ], ]; }}

    delete() 方法的调用将标记记录为"已经删除",而不是删除它:

    $id=17;$item=Item::findOne($id);$item->delete(); // no record removal, mark record as"deleted" instead$item=Item::findOne($id);var_dump($item->isDeleted); // outputs"true"

    请注意, Heads delete() 方法,它将无法使用ActiveRecord事务功能,带有 [[yiidbActiveRecord::OP_DELETE] ] 或者 [[yiidbActiveRecord::OP_ALL] ] 事务级别的比如 方案,这将是无法实现的:

    classItemextendsActiveRecord{publicfunctionbehaviors() {return ['softDeleteBehavior'=> ['class'=>SoftDeleteBehavior::className(),'replaceRegularDelete'=>true// mutate native `delete()` method ], ]; }publicfunctiontransactions() {return ['some'=>self::OP_DELETE, ]; }}$item=Item::findOne($id);$item->setScenario('some');$item->delete(); // nothing happens!

    提示:可以以将过滤"未删除"记录的条件应用于ActiveQuery作为默认范围,重写 find() 方法。 还要记住,你可以使用 where() 方法在空条件下重置这里缺省范围。

    classItemextendsActiveRecord{publicfunctionbehaviors() {return ['softDeleteBehavior'=> ['class'=>SoftDeleteBehavior::className(),'softDeleteAttributeValues'=> ['isDeleted'=>true ], ], ]; }publicstaticfunctionfind() {returnparent::find()->where(['isDeleted'=>false]); }}$notDeletedItems=Item::find()->all(); // returns only not"deleted" records$allItems=Item::find()->where([])->all(); // returns all records

    智能删除

    通常使用"柔和"删除特性来防止数据库历史丢失,并且可以能有引用或者依赖关系。 但是有时也允许对这样的数据进行实际删除。 for通常是在系统中浏览用户列表,但不能在系统中找到帐户,但在系统中找到帐户时,这些记录没有任何价值,可以从数据库中删除这些记录,以便保存磁盘空间。

    如果记录可以从数据库中删除或者仅被标记为"已经删除",则可以将"柔和"删除为"智能"并进行检测。 这可以通过 [[yii2techarsoftdeleteSoftDeleteBehavior::$allowDeleteCallback] ] 完成。 例如:

    classUserextendsActiveRecord{publicfunctionbehaviors() {return ['softDeleteBehavior'=> ['class'=>SoftDeleteBehavior::className(),'softDeleteAttributeValues'=> ['isDeleted'=>true ],'allowDeleteCallback'=>function ($user) {return$user->lastLoginDate===null; // allow delete user, if he has never logged in } ], ]; }}$user=User::find()->where(['lastLoginDate'=>null])->limit(1)->one();$user->softDelete(); // removes the record!!!$user=User::find()->where(['not'=>['lastLoginDate'=>null]])->limit(1)->one();$user->softDelete(); // marks record as"deleted"

    在启用 [[yii2techarsoftdeleteSoftDeleteBehavior::$replaceRegularDelete] ]的情况下应用 [[yii2techarsoftdeleteSoftDeleteBehavior::$allowDeleteCallback] ] 逻辑。

    处理外键约束

    在支持外键( 如 MySQL 。postgre 等等 )的情况下,"柔和"删除被广泛使用来保持外键的一致性。 例如:如果用户在网上购买购买,有关这里购买的信息应保留在未来的记账系统中。 此类数据结构的DDL可能如下所示:

    CREATETABLE `Customer`
    (
     `id`integerNOT NULL AUTO_INCREMENT,
     `name`varchar(64) NOT NULL,
     `address`varchar(64) NOT NULL,
     `phone`varchar(20) NOT NULL,
     PRIMARY KEY (`id`)
    ) ENGINE InnoDB;CREATETABLE `Purchase`
    (
     `id`integerNOT NULL AUTO_INCREMENT,
     `customerId`integerNOT NULL,
     `itemId`integerNOT NULL,
     `amount`integerNOT NULL,
     PRIMARY KEY (`id`)
     FOREIGN KEY (`customerId`) REFERENCES`Customer` (`id`) ON DELETE RESTRICT ONUPDATE CASCADE,
     FOREIGN KEY (`itemId`) REFERENCES`Item` (`id`) ON DELETE RESTRICT ONUPDATE CASCADE,
    ) ENGINE InnoDB;

    因这里,在将外键从'购买'设置为'用户'时,使用'删除限制时'模式。 因此,尝试删除至少一个购买数据库错误的用户记录时,将发生。 但是,如果用户记录没有外部引用,则可以将它的删除。

    对于这样的用例,[[yii2techarsoftdeleteSoftDeleteBehavior::$allowDeleteCallback] ]的使用并不十分实用。 如果外部引用存在或者不存在,它需要执行额外的查询来消除外键数据库功能的好处。

    方法 [yii2techarsoftdeleteSoftDeleteBehavior::safeDelete()] ] 尝试调用常规 [[yiidbBaseActiveRecord::delete()] ] 方法,如果它失败,则返回到 [[yii2techarsoftdeleteSoftDeleteBehavior::softDelete()] ] 。

    // if there is a foreign key reference :$customer=Customer::findOne(15);var_dump(count($customer->purchases)); // outputs;"1"$customer->safeDelete(); // performs"soft" delete!var_dump($customer->isDeleted) // outputs:"true"// if there is NO foreign key reference :$customer=Customer::findOne(53);var_dump(count($customer->purchases)); // outputs;"0"$customer->safeDelete(); // performs actual delete!$customer=Customer::findOne(53);var_dump($customer); // outputs:"null"

    默认情况下 safeDelete() 方法捕获 [[yiidbIntegrityException] ] 异常,这意味着将对外部约束违反数据库异常执行软删除。 你可以在这里指定另一个异常类来自定义回退错误级别。 例如:[[Exception] ]的使用会导致软删除回退在常规删除的任何错误中。

    记录恢复

    在某些时候,你可能希望"还原"记录,这些记录已经被标记为"已经删除"。 你可以为此使用 restore() 方法:

    $id=17;$item=Item::findOne($id);$item->softDelete(); // mark record as"deleted"$item=Item::findOne($id);$item->restore(); // restore recordvar_dump($item->isDeleted); // outputs"false"

    默认情况下,应该从 [[yii2techarsoftdeleteSoftDeleteBehavior::$softDeleteAttributeValues] ] 自动检测应用于记录恢复的属性值,但是最好通过 [[yii2techarsoftdeleteSoftDeleteBehavior::$restoreAttributeValues] ] 来显式地指定它们。

    事件

    默认情况下 [[yii2techarsoftdeleteSoftDeleteBehavior::softDelete()] ] 触发 [[yiidbBaseActiveRecord::EVENT_BEFORE_DELETE] ] 和 [[yiidbBaseActiveRecord::EVENT_AFTER_DELETE] ] 事件,方法是按照规则的delete() 触发它们。

    另外 [[yii2techarsoftdeleteSoftDeleteBehavior] ] 在所有者ActiveRecord的作用域中触发了几个附加事件:

    • [[yii2techarsoftdeleteSoftDeleteBehavior::EVENT_BEFORE_SOFT_DELETE] ] - 在进行"柔和"删除之前触发。
    • [[yii2techarsoftdeleteSoftDeleteBehavior::EVENT_AFTER_SOFT_DELETE] ] - 在进行"柔和"删除后触发。
    • [[yii2techarsoftdeleteSoftDeleteBehavior::EVENT_BEFORE_RESTORE] ] - 从"已经删除"状态恢复记录之前触发。
    • [[yii2techarsoftdeleteSoftDeleteBehavior::EVENT_AFTER_RESTORE] ] - 从"已经删除"状态恢复记录后触发。

    你可以将这些事件的事件处理程序附加到你的ActiveRecord对象:

    $item=Item::findOne($id);$item->on(SoftDeleteBehavior::EVENT_BEFORE_SOFT_DELETE, function($event) {$event->isValid=false; // prevent"soft" delete to be performed});

    你还可以通过声明相应的方法来在你的ActiveRecord类中处理这些事件:

    classItemextendsActiveRecord{publicfunctionbehaviors() {return ['softDeleteBehavior'=> ['class'=>SoftDeleteBehavior::className(),//.. . ], ]; }publicfunctionbeforeSoftDelete() {$this->deletedAt=time(); // log the deletion datereturntrue; }publicfunctionbeforeRestore() {return$this->deletedAt> (time() -3600); // allow restoration only for the records, being deleted during last hour }}



    Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语