帮酷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  |  如果智培  |  酷兔英语