staudenmeir / laravel-merged-relations
合并Laravel Eloquent关系
Requires
- php: ^8.2
- illuminate/database: ^11.0
- staudenmeir/laravel-migration-views: ^1.9.1
Requires (Dev)
- barryvdh/laravel-ide-helper: ^3.0
- orchestra/testbench: ^9.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11.0
- staudenmeir/eloquent-has-many-deep: ^1.20
README
这个Laravel Eloquent扩展允许使用SQL视图合并多个关系。
这些关系可以针对相同的或不同的相关模型。
支持Laravel 5.5+。
安装
composer require staudenmeir/laravel-merged-relations:"^1.0"
如果您在Windows上的PowerShell中(例如在VS Code中),请使用此命令
composer require staudenmeir/laravel-merged-relations:"^^^^1.0"
版本
用法
使用案例
使用此包合并多个多态关系
class Tag extends Model { public function allTaggables() { // TODO } public function posts() { return $this->morphedByMany(Post::class, 'taggable'); } public function videos() { return $this->morphedByMany(Video::class, 'taggable'); } }
或者使用它来合并不同深度的关系
class User extends Model { public function allComments() { // TODO } public function comments() { return $this->hasMany(Comment::class); } public function postComments() { return $this->hasManyThrough(Comment::class, Post::class); } }
步骤 1: 创建视图
在定义新关系之前,您需要在迁移中创建合并视图
use Staudenmeir\LaravelMergedRelations\Facades\Schema; Schema::createMergeView( 'all_taggables', [(new Tag)->posts(), (new Tag)->videos()] );
默认情况下,视图不会删除重复项。使用createMergeViewWithoutDuplicates()
获取唯一结果
use Staudenmeir\LaravelMergedRelations\Facades\Schema; Schema::createMergeViewWithoutDuplicates( 'all_comments', [(new User)->comments(), (new User)->postComments()] );
您也可以替换现有的视图
use Staudenmeir\LaravelMergedRelations\Facades\Schema; Schema::createOrReplaceMergeView( 'all_comments', [(new User)->comments(), (new User)->postComments()] );
此包包括staudenmeir/laravel-migration-views。您可以使用其方法重命名和删除视图
use Staudenmeir\LaravelMergedRelations\Facades\Schema; Schema::renameView('all_comments', 'user_comments'); Schema::dropView('all_comments');
如果您使用php artisan migrate:fresh
,可以使用--drop-views
删除所有视图。
步骤 2: 定义关系
创建视图后,您可以定义合并关系。
在您的模型中使用HasMergedRelationships
特质并提供视图名称
class Tag extends Model { use \Staudenmeir\LaravelMergedRelations\Eloquent\HasMergedRelationships; public function allTaggables(): \Staudenmeir\LaravelMergedRelations\Eloquent\Relations\MergedRelation { return $this->mergedRelation('all_taggables'); } }
如果所有原始关系都针对相同的关联模型,则可以使用mergedRelationWithModel()
。这允许您访问局部作用域并使用诸如whereHas()
或withCount()
之类的函数
class User extends Model { use \Staudenmeir\LaravelMergedRelations\Eloquent\HasMergedRelationships; public function allComments(): \Staudenmeir\LaravelMergedRelations\Eloquent\Relations\MergedRelation { return $this->mergedRelationWithModel(Comment::class, 'all_comments'); } }
您可以将合并关系像任何其他关系一样使用
$taggables = Tag::find($id)->allTaggables()->latest()->paginate(); $users = User::with('allComments')->get();
枢纽表数据
如果您的合并视图由多对多关系组成,则可以检索额外的枢纽列
将所需的枢纽列添加到所有关系
use Staudenmeir\LaravelMergedRelations\Facades\Schema; Schema::createMergeView( 'all_taggables', [ (new Tag)->posts()->withPivot('tagged_at'), (new Tag)->videos()->withPivot('tagged_at'), ] ); $taggables = Tag::find($id)->allTaggables; foreach ($taggables as $taggable) { dump($taggable->pivot->tagged_at); }
限制
在原始关系中,目前无法限制所选列或应用withCount()
。
在合并关系中,无法删除全局作用域,例如SoftDeletes
。它们只能在原始关系中删除。
测试
如果您使用PHPUnit或类似工具运行测试,请将此属性添加到您的基测试类中,以确保在清理测试数据库时删除数据库视图
protected bool $dropViews = true;
贡献
有关详细信息,请参阅CONTRIBUTING和行为准则。