bkwld / cloner
一个 Laravel Eloquent 模型的特质,允许您克隆模型及其关系,包括文件。
Requires
- php: >=7.0
- illuminate/support: ^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0
Requires (Dev)
- bkwld/upchuck: ^2.6@dev
- illuminate/database: ^5.5|^6.0|^10.0|^11.0
- league/flysystem-vfs: ^1.0
- mockery/mockery: ^1.2.3
- phpunit/phpunit: ~6.0|~8.0|^9.5.10|^10.5
- satooshi/php-coveralls: ^1.0
Suggests
- bkwld/upchuck: Required for replicating of files.
README
一个 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_relations
,Cloner
也会继续复制它们。
注意:多对多关系不会克隆到不同的数据库,因为相关的实例可能不存在于另一个数据库中,或者可能有不同的主键。
自定义克隆属性
默认情况下,Cloner
不会复制 id
(或您为模型定义的任何 key
)字段;它假设新的值将被自动增量。它也不会复制 created_at
或 updated_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; });