1

我有一个问题可能有点傻。我正在尝试复制模型实例并将其存储在变量中以调用该loadMissing方法。loadMissing这个想法是在不受原始模型影响的情况下调用方法。让我解释。

我的User模型中有以下方法:

class User extends Authenticatable
{
   ...

   public function myCustomMethod()
   {
        $cloned = $this->replicate()
            ->loadMissing(['roles', 'roles.permissions'])
            ->getAttribute('roles')
            ->flatMap(function ($role) {
                return $role->permissions
            });

        return $cloned;
   }

问题是,以这种方式,原始模型实例受到影响,并且它在原始实例中加载了我仅在此方法中加载的所有关系。我的问题是:有没有办法在模型实例的副本中加载和隔离关系而不影响原始模型?

提前致谢。

编辑 1

我也尝试过克隆实例并尝试loadMissing在克隆实例上使用该方法,但原始实例也受到影响。例如:

class User extends Authenticatable
{
   ...

   public function myCustomMethod()
   {
        $original = $this;
        $cloned = clone $original;

        $cloned->loadMissing('roles.permissions');

        dump($original);
        dump($cloned);

        die();
   }

但是通过这种方式,我得到了以下结果。请注意,当我试图在克隆实例中加载关系时,原始实例和克隆实例都在加载关系:

$original

1

$cloned

图像

我想知道这是否是正常行为。如果这是正常行为,我想不是,我想知道是否有任何方法可以在loadMissing不修改原始实例的情况下在实例的副本、副本或克隆上使用该方法。非常感谢您提前。

编辑 2

我的控制器看起来像这样简单:

class HomeController extends Controller
{
    public function index()
    {
        dd(User::find(1)->myCustomMethod());
    }
}

解决方案

经过几天寻找文档,进行测试并稍微拉扯一下头发,我找到了解决问题的方法并分享它,以防将来有人来这里寻找类似的信息。

基本上,帮助我找到正确方法的答案是:

https://stackoverflow.com/a/29787693/13066106

官方 PHP 文档中记录了这一点:

https://www.php.net/manual/en/language.oop5.cloning.php

我在这里逐字复制并粘贴最相关的内容:

当一个对象被克隆时,PHP 将对该对象的所有属性执行一个浅拷贝。任何引用其他变量的属性都将保持引用。

当我到达这一点时,我明白它为什么不起作用......我正在克隆一个类型的集合,Illuminate\Database\Eloquent\Collection这个集合包含多个类型的对象Role,但根据文档,当我修改任何属性时,这是正常行为在克隆实例中,更改将在原始实例中反映给我。

从这里,我查找了有关它的更多文档,并找到了一篇绝对帮助我解决问题的文章:

不要克隆你的 php 对象,DeepCopy 他们

这篇文章的描述性很强,基本上它的作用是建议使用包DeepCopy

幸运的是,这个包默认已经是 Laravel 的依赖了,所以我不必用 composer 安装它。我只是使用该deep_copy方法克隆实例。

非常感谢所有以某种方式帮助过我的人。我希望我分享的文档链接对那些来这里寻找类似信息的人有用。

4

1 回答 1

2

为什么不直接获取权限集合(模型之外):

$userId = $user->id;
$premissions = Permissions::whereHas('users', function($userQuery) use ($userID) {
        $userQuery->where('id',$userId);
    })
    ->get();

或者做平面图:

$result = Roles::with('permissions')
    ->whereHas('users', function($userQuery) use ($userID) {
        $userQuery->where('id',$userId);
    })
    ->get()
    ->flatMap(function ($role) {
        return $role->permissions
    });
于 2021-08-09T21:33:17.670 回答