【问题标题】:How to reload/refresh model from database in Laravel?如何从 Laravel 的数据库中重新加载/刷新模型?
【发布时间】:2014-07-01 19:37:33
【问题描述】:

在我的一些测试中,我创建了一个用户模型,并运行了一些需要保存某些属性的方法。在 Rails 中,我通常会调用类似 user.reload 的名称,它会重新填充数据库中的属性。

laravel 有没有办法做到这一点?我通读了 api 并找不到它的方法:http://laravel.com/api/4.1/Illuminate/Database/Eloquent/Model.html 关于“正确”方法的任何想法?

【问题讨论】:

标签: php laravel unit-testing laravel-4 eloquent


【解决方案1】:

8 月份有一个commit 提交给 4.0 分支,添加了一个 reload() 方法,但目前还没有与较新的 Laravel 分支合并。

但是... Laravel 5 提供了一个“fresh()”方法,它将返回当前模型的一个新实例。使用 Laravel 5.0 或更高版本后,您可以像这样重新加载模型:

$model = $model->fresh(); 

请注意,fresh() 不会直接更新您现有的 $model,它只是返回一个新实例,因此我们需要使用“$model =”。它还接受一个参数这是您希望它急切加载的关系数组。

如果你还没有使用 Laravel 5 但你想要相同的功能,你可以将此方法添加到你的模型中:

public function fresh(array $with = array())
{
    $key = $this->getKeyName();
    return $this->exists ? static::with($with)->where($key, $this->getKey())->first() : null;
}

更新:如果您使用的是 Laravel 5.4.24 或更高版本,现在有一个 $model->refresh() 方法,您可以使用它来刷新对象的属性和关系,而不是获取新的像fresh() 这样的对象。有关详细信息,请参阅 Jeff Puckett 的回答。

【讨论】:

  • 使用 laravel-5 标签可能值得为此创建一个新问题。
【解决方案2】:

感谢PR#19174 可用,因为5.4.24refresh 方法。

$model->refresh();

这样您就不必像其他答案中所示的fresh 方法那样处理重新分配,如果您想刷新已传递给另一个方法的模型,这通常没有帮助,因为变量分配将超出调用上下文的范围以供以后使用。

【讨论】:

  • 这在使用模型事件时也很有效!
  • refresh 工作时,fresh 对我不起作用。我正在使用 Laravel 5.7
  • @Yevgeniy Afanasyev - fresh() 返回一个 new 模型实例,因此您必须调用 $model = $model->fresh(),而 refresh() 会重新加载模型。
  • Laravel 文档链接已损坏。
  • @ChristosLytras 感谢您的提醒。看起来他们删除了不受支持版本的旧文档。查看当前版本,它并没有真正的帮助,因此我没有尝试使用未来的版本进行维护,而是完全删除了链接
【解决方案3】:
  • refresh() 是一个可变操作:它将从数据库中重新加载当前模型实例。
  • fresh() 是一个不可变的操作:它从数据库中返回一个新的模型实例。它不会影响当前实例。
// Database state:
$user=User::create([
  'name' => 'John',
]);

// Model (memory) state:
$user->name = 'Sarah';

$user2 = $user->fresh();
// $user->name => 'Sarah';
// $user2->name => 'John'

$user->refresh();
// $user->name => 'John'

【讨论】:

    【解决方案4】:

    我也看不到。看起来你必须:

    $model = $model->find($model->id);
    

    您也可以自己创建一个:

    public function reload()
    {
        $instance = new static;
    
        $instance = $instance->newQuery()->find($this->{$this->primaryKey});
    
        $this->attributes = $instance->attributes;
    
        $this->original = $instance->original;
    }
    

    刚刚在这里测试过,看起来可以,但不确定这能走多远,不过,Eloquen 是一个相当大的类。

    【讨论】:

    • -1:“刚刚在这里进行了测试,看起来它可以工作,但不确定这能走多远” - 这通常是正确的关键。另外,$model->refresh(); 现已推出。
    【解决方案5】:

    我相信@Antonio 的回答是最正确的,但根据用例,您也可以使用$model->setRawAttributes$model->getAttributes 的组合。

    $users = User::all();
    
    foreach($users as $user)
    {
        $rawAttributes = $user->getAttributes();
    
        // manipulate user as required 
        // ..
        // Once done, return attribute state
    
        $user->setRawAttributes($rawAttributes);
    }
    

    这样做的主要缺点是您只是“重新加载”数据属性,而不是您更改的任何关系等。这也可能被认为是有利的一面。

    编辑

    从 L5 开始 - fresh() 是要走的路

    【讨论】:

      最近更新 更多