ChatGPT解决这个技术问题 Extra ChatGPT

如何从 Laravel 的数据库中重新加载/刷新模型?

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

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

也许 getDirty() 方法可以帮助你。 laravel.com/api/…

L
LinusGeffarth

有一个 commit 在 8 月份提交到 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() 方法,您可以使用它来刷新对象的属性和关系,而不是获取新的对象,例如 { 2} 确实如此。有关更多详细信息,请参阅 Jeff Puckett 的回答。


使用 laravel-5 标签为此创建一个新问题可能是值得的。
J
Jeff Puckett

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

$model->refresh();

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


这在使用模型事件时也很有效!
refresh 工作时,fresh 不适合我。我正在使用 Laravel 5.7
@Yevgeniy Afanasyev - fresh() 返回一个 new 模型实例,因此您必须调用 $model = $model->fresh(),而 refresh() 会重新加载模型。
Laravel 文档链接已损坏。
@ChristosLytras 感谢您的提醒。看起来他们删除了不受支持版本的旧文档。查看当前版本,它并没有真正的帮助,因此我没有尝试使用未来版本进行维护,而是完全删除了链接
i
igaster

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'

A
Andy Fleming

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

$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();
C
Chris

我相信@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() 是要走的路