自定义Laravel关系? [英] Custom Laravel Relations?

查看:81
本文介绍了自定义Laravel关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设情况:假设我们有3种模型:

Hypothetical situation: Let's say we have 3 models:

  • User
  • Role
  • Permission
  • User
  • Role
  • Permission

我们也可以说UserRole具有多对多关系,而RolePermission具有多对多关系.

Let's also say User has a many-to-many relation with Role, and Role has a many-to-many relation with Permission.

所以他们的模型可能看起来像这样. (我故意让他们简短.)

So their models might look something like this. (I kept them brief on purpose.)

class User
{
    public function roles() {
        return $this->belongsToMany(Role::class);
    }
}

class Role
{
    public function users() {
        return $this->belongsToMany(User::class);
    }

    public function permissions() {
        return $this->belongsToMany(Permission::class);
    }
}

class Permission
{
    public function roles() {
        return $this->belongsToMany(Role::class);
    }
}

如果要获取User的所有Permission,怎么办?没有BelongsToManyThrough.

似乎您在做一些感觉不正确的事情,并且不适用于User::with('permissions')User::has('permissions')之类的事情.

It seems as though you are sort of stuck doing something that doesn't feel quite right and doesn't work with things like User::with('permissions') or User::has('permissions').

class User
{
    public function permissions() {
        $permissions = [];
        foreach ($this->roles as $role) {
            foreach ($role->permissions as $permission) {
                $permissions = array_merge($permissions, $permission);
            }
        }
        return $permissions;
    }
}

这个例子只是一个例子,请不要过多地阅读它.关键是,如何定义 custom 关系?另一个例子可能是Facebook评论与作者的母亲之间的关系.很奇怪,我知道,但希望您能明白.自定义关系.怎么样?

This example is, just one example, don't read too much into it. The point is, how can you define a custom relationship? Another example could be the relationship between a facebook comment and the author's mother. Weird, I know, but hopefully you get the idea. Custom Relationships. How?

在我看来,一个好的解决方案是以与描述Laravel中任何其他关系类似的方式描述这种关系.返回Eloquent Relation的东西.

In my mind, a good solution would be for that relationship to be described in a similar way to how describe any other relationship in Laravel. Something that returns an Eloquent Relation.

class User
{
    public function permissions() {
        return $this->customRelation(Permission::class, ...);
    }
}

这样的东西已经存在吗?

推荐答案

与解决方案最接近的是@biship

The closest thing to a solution was what @biship posted in the comments. Where you would manually modify the properties of an existing Relation. This might work well in some scenarios. Really, it may be the right solution in some cases. However, I found I was having to strip down all of the constraints added by the Relation and manually add any new constraints I needed.

我的想法是...如果您要每次剥离constraints,以使Relation只是裸露".为什么不创建一个自定义Relation,该自定义Relation本身不添加任何constraints并使用一个Closure来帮助促进添加constraints?

My thinking is this... If you're going to be stripping down the constraints each time so that the Relation is just "bare". Why not make a custom Relation that doesn't add any constraints itself and takes a Closure to help facilitate adding constraints?

类似的事情对我来说似乎很好.至少,这是基本概念:

Something like this seems to be working well for me. At least, this is the basic concept:

class Custom extends Relation
{
    protected $baseConstraints;

    public function __construct(Builder $query, Model $parent, Closure $baseConstraints)
    {
        $this->baseConstraints = $baseConstraints;

        parent::__construct($query, $parent);
    }

    public function addConstraints()
    {
        call_user_func($this->baseConstraints, $this);
    }

    public function addEagerConstraints(array $models)
    {
        // not implemented yet
    }

    public function initRelation(array $models, $relation)
    {
        // not implemented yet
    }

    public function match(array $models, Collection $results, $relation)
    {
        // not implemented yet
    }

    public function getResults()
    {
        return $this->get();
    }
}

尚未实现的方法用于急切加载,并且必须声明为抽象方法.我还没走呢:)

The methods not implemented yet are used for eager loading and must be declared as they are abstract. I haven't that far yet. :)

以及使此新Custom关系更易于使用的特征.

And a trait to make this new Custom Relation easier to use.

trait HasCustomRelations
{
    public function custom($related, Closure $baseConstraints)
    {
        $instance = new $related;
        $query = $instance->newQuery();

        return new Custom($query, $this, $baseConstraints);
    }
}

用法

// app/User.php
class User
{
    use HasCustomRelations;

    public function permissions()
    {
        return $this->custom(Permission::class, function ($relation) {
            $relation->getQuery()
                // join the pivot table for permission and roles
                ->join('permission_role', 'permission_role.permission_id', '=', 'permissions.id')
                // join the pivot table for users and roles
                ->join('role_user', 'role_user.role_id', '=', 'permission_role.role_id')
                // for this user
                ->where('role_user.user_id', $this->id);
        });
    }
}

// app/Permission.php
class Permission
{
    use HasCustomRelations;

    public function users()
    {
        return $this->custom(User::class, function ($relation) {
            $relation->getQuery()
                // join the pivot table for users and roles
                ->join('role_user', 'role_user.user_id', '=', 'users.id')
                // join the pivot table for permission and roles
                ->join('permission_role', 'permission_role.role_id', '=', 'role_user.role_id')
                // for this permission
                ->where('permission_role.permission_id', $this->id);
        });
    }
}

You could now do all the normal stuff for relations without having to query in-between relations first.

Github

我走了一步,把所有这些放在Github上,以防万一还有更多对这样的事情感兴趣的人.在我看来,这仍然是一种科学实验.但是,嘿,我们可以一起解决这个问题. :)

Github

I went a ahead and put all this on Github just in case there are more people who are interested in something like this. This is still sort of a science experiment in my opinion. But, hey, we can figure this out together. :)

这篇关于自定义Laravel关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆