」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > Laravel SoftDelete:避免唯一約束問題

Laravel SoftDelete:避免唯一約束問題

發佈於2024-11-06
瀏覽:792

Laravel SoftDelete: Avoiding the Unique Constraint Problem

本文源自https://medium.com/@hafiqiqmal93/laravel-softdelete-avoiding-the-unique-constraint-problem-45381d9745a0

如果您已经使用 Laravel 一段时间,特别是当项目涉及数据完整性时,您很可能已经遇到过 SoftDelete 功能。非常有用,因为您可以“删除”记录,而无需真正将它们从数据库中取出。 Laravel 所做的只是添加一个deleted_at 时间戳,以便将其标记为已删除,但仍保留在系统中。保留历史数据固然很好,但它确实引入了一个潜在的棘手问题——当您恢复软删除记录时,唯一约束会发生什么情况?


当您想要恢复数据库中已有的记录(例如唯一的电子邮件或用户名)时,这就会成为问题。 Laravel 只会抛出一个错误并停止进程。幸运的是,有一种简单的方法可以非常干净地避免这个问题。

让我们使用一个特性来演示一个解决方案,该特性将帮助您绕过在 Laravel 中使用 SoftDelete 时的独特约束。

了解问题

让我们举一个基本的例子。假设您有一个用户表,其中的电子邮件字段必须是唯一的:


Schema::create('users', function (Blueprint $table) {
    $table->string('email')->unique();
    $table->softDeletes();
});


如果您软删除电子邮件地址为 [email protected] 的用户,然后使用同一电子邮件地址创建一个新用户,Laravel 会抱怨电子邮件字段的唯一约束,并引发错误。在同样的情况下,当你尝试恢复已删除的用户时,Laravel 也会抱怨电子邮件字段的唯一约束并抛出相同的错误。

这变得令人头痛,尤其是在处理记录恢复是一项常见任务的大型系统时。

为了防止这种情况,我们可以在软删除记录时临时更改唯一字段的值,并在恢复记录时恢复原始值。这样,数据库在软删除或恢复期间就不会超出唯一约束。

解决方案:使用特征来避免重复约束

Laravel 特征是封装此功能的好方法。这是我们可以用来处理问题的一个特征:


trashed()) {
                foreach ($model->getDuplicateAvoidColumns() as $column) {
                    // handle for Spatie Translatable library
                    if (method_exists($model, 'getTranslatableAttributes')) {
                        $translates = $model->getTranslatableAttributes();
                        if (in_array($column, $translates)) {
                            foreach ($translates as $translate) {
                                if ($translate === $column) {
                                    $values = $model->getTranslations($column);
                                    foreach ($values as $translation => $value) {
                                        $values[$translation] = (explode('--', $value)[1] ?? $value);
                                    }
                                    $model->setTranslations($column, $values);
                                    break;
                                }
                            }
                            continue;
                        }
                    }
                    if ($value = (explode('--', $model->{$column})[1] ?? null)) {
                        $model->{$column} = $value;
                    }
                }
            }
        });
        static::deleted(function ($model): void {
            foreach ($model->getDuplicateAvoidColumns() as $column) {
                // handle for Spatie Translatable library
                if (method_exists($model, 'getTranslatableAttributes')) {
                    $translates = $model->getTranslatableAttributes();
                    if (in_array($column, $translates)) {
                        foreach ($translates as $translate) {
                            if ($translate === $column) {
                                $values = $model->getTranslations($column);
                                foreach ($values as $translation => $value) {
                                    $values[$translation] = time() . '--' . $value;
                                }
                                $model->setTranslations($column, $values);
                                break;
                            }
                        }
                        continue;
                    }
                }
                $model->{$column} = time() . '--' . $model->{$column};
            }
            $model->save();
        });
    }
}


这个特质有几件事:

  • 删除时,它将时间戳附加到唯一字段,本质上使该字段再次唯一,而不影响原始值。此技巧对于在软删除记录时保持满足唯一约束很有用。
  • 恢复时,它会去除时间戳,恢复唯一字段的原始值。

运作原理:

  • 唯一字段处理:每当删除具有此特征的模型时,该特征都会将时间戳附加到您想要保持唯一的字段(例如:电子邮件、用户名)。如果您尝试添加具有相同唯一值的新记录,这可以防止冲突。
  • 处理可翻译字段: 如果您的模型使用 Spatie Translatable 库,则此特征也足够智能,可以处理多语言字段。它查找可翻译的属性,调整它们的值,并使用时间戳技巧保存它们。
  • 恢复:当您恢复软删除的记录时,该特征会从唯一字段中去除时间戳,将字段返回到其原始值。

将特征应用到您的模型中

以下是如何在 Laravel 模型中应用此特征的方法:


class User extends Model
{
    use SoftDeletes, AvoidDuplicateConstraintSoftDelete;
    // Specify which columns should avoid the unique constraint issue
    public function getDuplicateAvoidColumns(): array
    {
        return ['email', 'username'];
    }
}


通过将 **AvoidDuplicateConstraintSoftDelete** 特征添加到模型中并指定哪些列需要避免唯一约束冲突(例如 emailusername),您可以轻松防止这些问题.

为什么这种方法有效?

这意味着,在软删除记录的情况下,由于某些独特的约束,不会导致与进一步操作的冲突。或者,换句话说,通过这种方式,您将能够通过将时间戳附加到唯一字段,使数据库的记录在唯一性方面“隐藏”,但在需要时仍然可以恢复。

当您处理大型数据库并且记录恢复很常见时,这非常有用。每当您引入软删除用户或任何其他模型时,您不必每次都处理“重复条目”错误。


最后的想法

Laravel 中最有用的东西是 SoftDelete,但有时它在处理独特约束时会让人头疼。这里有一个简单的、基于特征的解决方案,它将提供一种避免问题的优雅方法,只需在删除和恢复时临时更改唯一字段即可。这样您将避免令人沮丧的错误,并让您的应用程序顺利工作,而不会破坏数据库中的唯一约束。

如果您的任何领域已实现多语言化或使用 Spatie 的 Translatable 等库,则上述解决方案在每种情况下都可以正常工作。 SoftDeletes 旨在为您提供灵活性,而不是妨碍您。通过上述小修复,您将避免大多数陷阱并保持数据整洁和用户满意。


通过将此特征添加到您的模型中,您将节省时间并减少麻烦,特别是当您处理软删除和恢复是频繁操作的大型数据集时。在你的 Laravel 项目中尝试一下,你会发现它如何顺利地处理那些棘手的独特约束问题!


感谢您的阅读!不要忘记订阅以随时了解系统设计和电子商务创新的最新动态。设计愉快!

如果您发现本文富有洞察力,并希望了解有关系统设计和技术趋势的更多内容,请务必关注我:-

推特:https://twitter.com/hafiqdotcom
领英:https://www.linkedin.com/in/hafiq93
给我买咖啡:https://paypal.me/mhi9388 /
https://buymeacoffee.com/mhitech
媒体:https://medium.com/@hafiqiqmal93

版本聲明 本文轉載於:https://dev.to/afiqiqmal/laravel-softdelete-avoiding-the-unique-constraint-problem-8k2?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 雷迪斯
    雷迪斯
    Redis 是一個 NOSQL 資料庫,資料以鍵值對的形式儲存。 Redis 將資料儲存在主記憶體上,這意味著它速度快,但易失性,不像 PostgreSQL 等資料庫系統將資料儲存在磁碟上。 概述 在具有伺服器和資料庫的應用程式中,存取資料庫上的資訊會導致延遲。 像redis這...
    程式設計 發佈於2024-11-06
  • 如何使用預先匯入的套件啟動 python 或 ipython。
    如何使用預先匯入的套件啟動 python 或 ipython。
    不必每次執行 python 或 ipython 時都必須編寫“import os”或其他常見包,此腳本將啟動 python 並導入這些包 #!/usr/bin/env bash # -----------------------------------------------------------...
    程式設計 發佈於2024-11-06
  • python中的資料類型
    python中的資料類型
    內建資料型別 文字類型:字串 數值類型:int、float、complex 序列類型:清單、元組、範圍 映射類型:字典 集合類型:集合、凍結集合 布林類型:bool 二進位類型:位元組、位元組數組、記憶體視圖 無型別:無型別 程式 a=「阿維納什」 印刷(類型(a)) b=45 印刷(類型(b)) ...
    程式設計 發佈於2024-11-06
  • JavaScript 中的提升
    JavaScript 中的提升
    什么是 JavaScript 提升? 提升是指 JavaScript 中在执行之前进行声明的过程。首先处理变量和函数声明。因此,即使变量在声明之前被引用,也不会导致错误,而是返回 undefined。对于函数声明,整个函数被提升,这意味着它可以在代码中定义之前使用。此过程在执行开始...
    程式設計 發佈於2024-11-06
  • 如何在 Go 中同時選擇緩衝發送和無緩衝接收通道?
    如何在 Go 中同時選擇緩衝發送和無緩衝接收通道?
    同時選擇 Go 發送和接收通道在 Go 中,可以使用 select 語句在通道上執行非阻塞 I/O 操作。然而,在處理緩衝發送通道(chan
    程式設計 發佈於2024-11-06
  • 如何將列表列表轉換為統一的 NumPy 陣列?
    如何將列表列表轉換為統一的 NumPy 陣列?
    將清單清單轉換為NumPy 陣列資料分析中的一個常見任務是將清單清單轉換為NumPy 陣列高效率的數值運算。這個數組可以透過將每個列表分配給一行來形成,列表中的每個元素佔據一列。 選項 1:陣列陣列如果子清單有不同的長度,適當的方法是建立陣列的陣列。這保留了清單清單的原始結構,從而可以輕鬆檢索特定元...
    程式設計 發佈於2024-11-06
  • 前端的頂級設計模式
    前端的頂級設計模式
    在过去的几个月里,我为前端开发人员分享了一些流行的设计模式。其中包括 Singleton、Facade、Observer、Publisher/Subscriber 等模式。今天,我想总结一下这些模式的一些要点和好处,以及如何使用它们来改进您的前端开发流程。 什么是设计模式 设计模式是...
    程式設計 發佈於2024-11-06
  • ServBay版本.pdate公告
    ServBay版本.pdate公告
    我們很高興地宣布新版本 1.4.4 已經到來!讓我們來看看新增的備受期待的新功能。 新功能 CA和憑證管理: 統一SSL憑證管理平台:全新的憑證管理平台,旨在簡化憑證申請與管理流程。 ServBay User CA 和 ServBay Public CA: 引入 ...
    程式設計 發佈於2024-11-06
  • Spring框架中的控制反轉
    Spring框架中的控制反轉
    控制反转(IoC)和依赖注入(DI)是Spring框架中的两个基本概念。传统上,对象负责创建和管理它们自己的依赖关系。然而,IoC 通过将对象创建和依赖管理的控制权移交给像 Spring 这样的框架来翻转这一责任。 这种转变有几个优点: 更简单的实现交换:只需对代码库进行最小的更改即可交换不同的实现...
    程式設計 發佈於2024-11-06
  • 使用 React 建立遞歸檔案系統:深入探討
    使用 React 建立遞歸檔案系統:深入探討
    簡介:在 React 中建構遞歸檔案系統 在現代 Web 開發中,建立互動式動態檔案系統是常見的要求。無論是管理文件、組織專案或建構複雜的資料結構,擁有強大的文件系統都至關重要。在這篇文章中,我們將探討如何在 React 中建立遞歸檔案系統,並專注於可以新增、重新命名或刪除的嵌套資...
    程式設計 發佈於2024-11-06
  • SQL 查詢速度慢?使用此技術提高應用程式的效能
    SQL 查詢速度慢?使用此技術提高應用程式的效能
    挑戰 在我的應用程式(React Spring Boot Oracle)中,處理大型資料集導致處理時間極為緩慢。我需要一種解決方案來提高效能而不影響準確性或完整性。 解決方案:NTILE 並行處理 NTILE 是一個功能強大的 SQL 視窗函數,旨在將結果集劃分為...
    程式設計 發佈於2024-11-06
  • 關於測試覆蓋率的真相
    關於測試覆蓋率的真相
    一個強而有力的真理。 看下面這段簡單明了的程式碼: function sum(a, b) { return a b; } 現在,讓我們為它寫一些測試: test('sum', () => { expect(sum(1, 2)).toBe(3); expect(...
    程式設計 發佈於2024-11-06
  • 為什麼我的 OpenGL 三角形無法在 Go 中渲染?調查頂點緩衝區問題。
    為什麼我的 OpenGL 三角形無法在 Go 中渲染?調查頂點緩衝區問題。
    Go 中的OpenGL 頂點緩衝區問題在Go 中嘗試使用OpenGL 顯示三角形時,使用者遇到了頂點緩衝區問題緩衝區無法渲染形狀。 Go 程式碼源自於教程,但與 C 程式碼不同的是,它沒有產生任何輸出。 問題原因問題的根本原因位於傳遞給 vertexAttrib.AttribPointer() 的參...
    程式設計 發佈於2024-11-06
  • 為什麼在 Linux 32 位元發行版上的 Go 程式中設定 `ulimit -n` 會導致「參數無效」錯誤?
    為什麼在 Linux 32 位元發行版上的 Go 程式中設定 `ulimit -n` 會導致「參數無效」錯誤?
    如何在 Go 程式中設定 ulimit -n? 問題使用者嘗試在 Go 程式中設定 ulimit -n使用 setrlimit 和 getrlimit 系統呼叫將其限制在程式內而不是全域。然而,在嘗試設定該值時出現錯誤,提示「參數無效」。 解決方案發現問題是由於 Linux 32 的 Getrlim...
    程式設計 發佈於2024-11-06
  • 如何在Python中創建無限深度的動態嵌套字典?
    如何在Python中創建無限深度的動態嵌套字典?
    未定義深度的動態嵌套字典在涉及複雜多層資料結構的場景中,經常會遇到變數嵌套字典的需求水平。雖然硬編碼插入語句是一種潛在的解決方案,但當事先未知嵌套深度時,這種方法是不切實際的。 要克服此限制,請考慮利用 Python 的 collections.defaultdict,它允許動態建立字典。可以使用下...
    程式設計 發佈於2024-11-06

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3