【问题标题】:Laravel - Simulating a process but not modifying original modelsLaravel - 模拟过程但不修改原始模型
【发布时间】:2015-05-02 10:31:19
【问题描述】:

如果没有另行通知,我需要以某种方式隔离一个范围或一个类以不修改 Eloquent 模型:

我有很多帐户和服务。每个帐户都有一堆关系(规则和限制),这些关系有助于确定它可以用来支付什么以及如何支付。

我现在需要做的是模拟购买一堆服务或服务组合。

  1. 因此,如果我有 X 帐户和 Y 服务,那么对于每次模拟再次查询/刷新关系,我将不得不发出太多请求,所以这不是一个选择。

    new Purchase($accounts, $services); 
    new Purchase($accounts, $otherServices);
    ...
    
  2. 接下来的逻辑步骤是加载所有关系,然后模拟购买过程。除非我完成模拟或第一次服务,否则对于下一次购买,所有值都已更改。

这是我的问题的简化版本:

    function doSomething($user)
    {
        $user->doneSomething = true;
    }

    $user = Auth::user();

    $user->doneSomething = false;

    doSomething($user);

    dd($user->doneSomething); // true -- But  this one time I want it to be false
  1. 好的,那么我必须在我的函数之后重置模型。如果我使用来自数据库的所有规则,这可能会更容易。

    $account->setRawAttributes($account->getOriginal())
    

但是现在我也想用同一个函数来模拟一些我在函数之前修改了账户和规则的情况。


我还考虑过使用 getAtributes() getRelations() 将所有内容转换为数组,然后使用它们。但后来我失去了使用所有模型功能的选项。

我也知道 Eloquent Model replicate() 函数。但这似乎很麻烦,最终我还需要在计算和更新的行上调用 save;


最后,为了再次说明问题,我需要在函数周围添加一个大气泡/隔离范围,这样任何 Eloquent 模型作为参数传入都将保持不变。

   // Purchse.php 

    public function calculate()
    {
        foreach($this->services as &$service)
            foreach($this->accounts as &$account)
                ...
    }

    // Calling the purchase:

    isolateEverything(function () {
        $purchase = new Purchase($accounts, $services);
        $result = $purchase->calculate();
    });

一种方法是在计算函数之前存储和替换。但是好像很多无用的代码。

另一种方法是以某种方式将函数与外界隔离。

实现这一切的最佳方法是什么?

【问题讨论】:

    标签: php laravel eloquent laravel-5


    【解决方案1】:

    我想我找到了一些可以帮助我的魔法方法。它们仍有待全面测试,但我的第一个简单实验表明这可能有效。

    我想我可以使用syncOriginal() 将值存储为原始值

        public function syncOriginal()
        {
            $this->original = $this->attributes;
    
            return $this;
        }
    

    然后在我完成计算并需要重置后,我可以同时调用setRawAttributes()getOriginal()

        $account->setRawAttributes($account->getOriginal());
    

    如果我不想更改原始属性,我可以创建类似的方法,例如 syncBackup()getBackup()

    看来我最终只需要找到一个正常的地方来存储备份值。

    当您寻找解决方案的时间太长以至于最终您在 SO 上提出问题并很快找到解决方案时的那种感觉。

    编辑:这是我目前制作的,似乎对我有用。

    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Support\Collection;
    
    class BaseModel extends Model {
    
        private $backup = array();
    
        public function createBackup()
        {
            $this->backup = $this->attributes;
    
            foreach ($this->getRelations() as $relation => $value) 
            {
                if($value instanceof self)
                {
                    $value->createBackup();
                }
            }
        }
    
        public function popBackup()
        {
            $this->setRawAttributes($this->backup);
    
            foreach ($this->getRelations() as $relation => $value) 
            {
                if($value instanceof self)
                {
                    $value->popBackup();
                }
            }
        }
    }
    

    从这里也可以创建备份数组并在需要时开始一个一个地弹出它们。这也可能是一种特质。

    【讨论】:

      猜你喜欢
      • 2016-01-07
      • 2015-11-05
      • 2023-03-22
      • 2015-08-08
      • 2021-03-22
      • 2019-05-15
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      相关资源
      最近更新 更多