save() 后 Laravel 关系的可用性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39520072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel Relationship availability after save()
提问by Sven E.
I'm building a simple timetracking App using Laravel 5 where I have two Laravel models, one called "User" and one called "Week"
我正在使用 Laravel 5 构建一个简单的时间跟踪应用程序,其中有两个 Laravel 模型,一个称为“用户”,一个称为“周”
The relationships are pretty simple:
Week.php:
关系非常简单:
Week.php:
public function user()
{
return $this->belongsTo('App\User');
}
User.php:
用户.php:
function weeks()
{
return $this->hasMany('App\Week');
}
Now, the User.php file also has a simple helper / novelty function called "getCurrentWeek()" that, as the name suggests, returns the current week
现在,User.php 文件还有一个名为“getCurrentWeek()”的简单帮助器/新奇函数,顾名思义,它返回当前周
function getCurrentWeek()
{
$possibleWeek = $this->weeks->sortByDesc('starts')->all();
if(count($possibleWeek) != 0)
{
return $possibleWeek[0];
}
else
{
return null;
}
}
My problem is: If I create the very first week for a user and attach / relate it to the user like so:
我的问题是:如果我为用户创建第一周并将其附加/关联到用户,如下所示:
$week = new Week;
//Omitted: Setting so attributes here ...
$week->user_id = $user->id;
$weeks->save()
$user->weeks()->save($week);
And then call the $user->getCurrentWeek();
method, that method returns null
, although a new week has been created, is related to the user and has been saved to the database. In my mind, the expected behaviour would be for getCurrentWeek()
to return the newly created week.
What am I misunderstanding about Eloquent here / doing just plain wrong?
然后调用该$user->getCurrentWeek();
方法,该方法返回null
,虽然已经创建了新的一周,但与用户相关并已保存到数据库中。在我看来,预期的行为是getCurrentWeek()
返回新创建的一周。
我在这里对 Eloquent 有什么误解/完全错误?
回答by patricus
Relationship attributes are lazy loaded the first time they are accessed. Once loaded, they are not automatically refreshed with records that are added or removed from the relationship.
关系属性在第一次访问时被延迟加载。加载后,它们不会使用在关系中添加或删除的记录自动刷新。
Since your getCurrentWeek()
function uses the relationship attribute, this code will work:
由于您的getCurrentWeek()
函数使用了关系属性,因此此代码将起作用:
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// $user->weeks attribute has not been accessed yet, so it will be loaded
// by the first access inside the getCurrentWeek method
dd($user->getCurrentWeek());
But, this code will not work:
但是,此代码将不起作用:
// accessing $user->weeks lazy loads the relationship
echo count($user->weeks);
// relate a new record
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// $user->weeks inside the method will not contain the newly related record,
// as it has already been lazy loaded from the access above.
dd($user->getCurrentWeek());
You can either modify your getCurrentWeek()
method to use the relationship method ($this->weeks()
) instead of the attribute ($this->weeks
), which will always hit the database, or you can reload the relationship (using the load()
method) after adding or removing records.
您可以修改您的getCurrentWeek()
方法以使用关系方法 ( $this->weeks()
) 而不是属性 ( $this->weeks
),这将始终命中数据库,或者您可以load()
在添加或删除记录后重新加载关系(使用该方法)。
Change the getCurrentWeek()
method to use the relationship method weeks()
(updated method provided by @Bjorn)
更改getCurrentWeek()
方法以使用关系方法weeks()
(@Bjorn 提供的更新方法)
function getCurrentWeek()
{
return $this->weeks()->orderBy('starts', 'desc')->first();
}
Or, refresh the relationship using the load()
method:
或者,使用以下load()
方法刷新关系:
// accessing $user->weeks lazy loads the relationship
echo count($user->weeks);
// relate a new record
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// reload the weeks relationship attribute
$user->load('weeks');
// this will now work since $user->weeks was reloaded by the load() method
dd($user->getCurrentWeek());
回答by Isometriq
Just to add to @patricus answer...
只是为了添加到@patricus 答案...
After save/create/update, you can also empty all the cached relation data like so:
$user->setRelations([]);
保存/创建/更新后,您还可以清空所有缓存的关系数据,如下所示:
$user->setRelations([]);
Or selectively:
$user->setRelation('weeks',[]);
或者有选择地:
$user->setRelation('weeks',[]);
After that, data will be lazy loaded again only when needed:
$user->weeks
之后,数据将仅在需要时再次延迟加载:
$user->weeks
That way you can continue using lazy loading.
这样你就可以继续使用延迟加载。
回答by Bj?rn
$user->weeks()->save($week);
is not needed because you manually attached the week to the user by using $week->user_id = $user->id;
and saving it.
$user->weeks()->save($week);
不需要,因为您通过使用$week->user_id = $user->id;
和保存将周手动附加到用户。
You could actually rewrite the whole function to:
您实际上可以将整个函数重写为:
function getCurrentWeek()
{
return $this->weeks->sortByDesc('starts')->first();
}
Or
或者
function getCurrentWeek()
{
return $this->weeks()->orderBy('starts', 'desc')->first();
}
Edit:
编辑:
I made a little proof of concept and it works fine like this:
我做了一些概念证明,它可以像这样正常工作:
App\User.php
应用\用户.php
function weeks()
{
return $this->hasMany('App\Week');
}
function getCurrentWeek()
{
return $this->weeks->sortByDesc('starts')->first();
}
App\Week.php
应用\Week.php
public function user()
{
return $this->belongsTo('App\User');
}
routes/web.php or App/Http/routes.php
route/web.php 或 App/Http/routes.php
Route::get('poc', function () {
$user = App\User::find(1);
$week = new App\Week;
$week->user_id = $user->id;
$week->starts = Carbon\Carbon::now();
$week->save();
return $user->getCurrentWeek();
});
Result:
结果:
{
id: 1,
user_id: "1",
starts: "2016-09-15 21:42:19",
created_at: "2016-09-15 21:42:19",
updated_at: "2016-09-15 21:42:19"
}