bkwld/cloner

一个 Laravel Eloquent 模型的特质,允许您克隆模型及其关系,包括文件。

3.12.0 2024-03-16 00:38 UTC

README

Packagist Build Status Coverage Status

一个 Laravel Eloquent 模型的特质,允许您克隆模型及其关系,包括文件。甚至可以克隆到另一个数据库。

安装

要开始使用 Cloner,请使用 Composer 将包添加到您的项目依赖中

composer require bkwld/cloner

注意:以下步骤在 Laravel 5.5 或更高版本中是可选的!

安装 cloner 包后,注册服务提供者。

Bkwld\Cloner\ServiceProvider::class,

在您的 config/app.php 配置文件中

'providers' => [
    /*
    * Package Service Providers...
    */
    Bkwld\Cloner\ServiceProvider::class,
],

用法

您的模型现在应该看起来像这样

class Article extends Eloquent {

   use \Bkwld\Cloner\Cloneable;
}

您可以像这样克隆一个 Article 模型

$clone = Article::first()->duplicate();

在这个例子中,$clone 是一个新创建的 Article,已经被保存到数据库中。要将克隆内容保存到不同的数据库中

$clone = Article::first()->duplicateTo('production');

其中 production 是不同 Laravel 数据库连接的 连接名称

克隆关系

假设您的 Article 有许多 Photos(一对多关系)和多个 Authors(多对多关系)。现在,您的 Article 模型应该像这样

class Article extends Eloquent {
   use \Bkwld\Cloner\Cloneable;

   protected $cloneable_relations = ['photos', 'authors'];

   public function photos() {
       return $this->hasMany('Photo');
   }

   public function authors() {
        return $this->belongsToMany('Author');
   }
}

$cloneable_relations 通知 Cloneable 在克隆时应该跟随哪些关系。现在当您调用 Article::first()->duplicate() 时,原始的 Photo 表的所有行将被复制,并关联到新的 Article。并且将创建新的中转行,将新的 Article 与原始的 Authors 关联(因为它是多对多关系,不会创建新的 Author 行)。此外,如果 Photo 模型与另一个模型有多对多关系,您可以在其类中指定 $cloneable_relationsCloner 也会继续复制它们。

注意:多对多关系不会克隆到不同的数据库,因为相关的实例可能不存在于另一个数据库中,或者可能有不同的主键。

自定义克隆属性

默认情况下,Cloner 不会复制 id(或您为模型定义的任何 key)字段;它假设新的值将被自动增量。它也不会复制 created_atupdated_at。您可以通过以下方式添加要忽略的附加属性

class Photo extends Eloquent {
   use \Bkwld\Cloner\Cloneable;

   protected $clone_exempt_attributes = ['uid', 'source'];

   public function article() {
        return $this->belongsTo('Article');
   }

   public function onCloning($src, $child = null) {
        $this->uid = str_random();
        if($child) echo 'This was cloned as a relation!';
        echo 'The original key is: '.$src->getKey();
   }
}

$clone_exempt_attributes 添加到默认值。如果您想完全替换默认值,则覆盖特质中的 getCloneExemptAttributes() 方法并返回一个数组。

此外,请注意示例中的 onCloning() 方法。它被用于确保一个唯一列保持唯一。当模型在复制过程中保存前和保存后立即调用:onCloning()onCloned()$child 参数允许您根据它是否作为关系或直接克隆来自定义行为。

此外,Cloner 在克隆过程中触发以下 Laravel 事件

  • cloner::cloning: ModelClass
  • cloner::cloned: ModelClass

ModelClass 是正在克隆的模型的类路径。事件负载包含克隆和原始模型实例。

克隆文件

如果你的模型引用了存储在磁盘上的文件,你可能需要复制这些文件并更新引用。否则,如果克隆被删除且发生级联删除,你将删除原始模型引用的文件。《Cloner》允许你指定文件附件适配器,并自带对Bkwld\Upchuck的支持。以下是一些示例用法:

class Photo extends Eloquent {
   use \Bkwld\Cloner\Cloneable;

   protected $cloneable_file_attributes = ['image'];

   public function article() {
        return $this->belongsTo('Article');
   }
}

$cloneable_file_attributes属性被Cloneable特性用于标识哪些列包含文件。它们的值传递给附件适配器,该适配器负责复制文件并返回新文件的路径。

如果你不使用Bkwld\Upchuck,你可以编写自己的Bkwld\Cloner\AttachmentAdapter特性实现,并将其封装在名为'cloner.attachment-adapter'的Laravel IoC容器中。例如,将以下内容放入你的app/start/global.php文件中:

App::singleton('cloner.attachment-adapter', function($app) {
   return new CustomAttachmentAdapter;
});