staudenmeir/laravel-merged-relations

合并Laravel Eloquent关系

v1.9.1 2024-05-17 15:36 UTC

README

CI Code Coverage Latest Stable Version Total Downloads License

这个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行为准则